home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / web / clip / unix / clip.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-11-16  |  258.6 KB  |  5,683 lines

  1.   (**********  #File "CLIP_UNIX.PAS" (#Indent on, #Comment on)   *******)
  2.   (*********************************************************************)
  3.   (* Program:     CLIP_2   - Code from LIterate Program: 2-nd pass     *)
  4.   (* Purpose:     Perform a run of the CLIP-system.                    *)
  5.   (* Interface:   CLIP.INI:   File which contains all the information  *)
  6.   (*                          for this particular run.                 *)
  7.   (*              <sources>:  Files containing the refinements.        *)
  8.   (*              <modules>:  Files containing the generated modules.  *)
  9.   (*********************************************************************)
  10.   PROGRAM CLIP_2 (INPUT, OUTPUT);
  11.   (*-----------   Global parameters of the CLiP system  ---------------*)
  12.   CONST
  13.       CLiP =              'Code from Literate Programs';
  14.       CLIP_VERSION =      'CLiP version 2.1';    (* Mod: EWvA 16/10/93 *)
  15.       DFLT_INIFILE =      'CLIP.INI';            (* Mod: EWvA 16/10/93 *)
  16.       DFLT_INIFILE_L =    8;                     (* Mod: EWvA 16/10/93 *)
  17.       STRING_FIXED_L =        132;
  18.       EMPTY_STRING_FIXED =    '                                            '+
  19.                               '                                            '+
  20.                               '                                            ';
  21.       MAX_FILE_SPEC_L =       132;
  22.       MAX_NR_FILE_SPECS =     64;
  23.       MAX_CHOICE_L =          100;
  24.       ALLOWED_ID_CHARS =      ['A'..'Z', 'a'..'z', '0'..'9', '.'];
  25.       ERROR_MSG_LENGTH =      80;
  26.       LOC_SPEC_L =            25;
  27.       CORRUPT_INI_FILE  =     1;        (* Error_code used by CLIP_MNU *)
  28.       FT_SIZE =               MAX_NR_FILE_SPECS;
  29.       MAX_LINE =              132;
  30.       ST_SIZE =               30000;
  31.       SP_SIZE =               65000;
  32.       SYNTAX_LEN =            10;
  33.       MAX_MODE_L =            16;
  34.       MAX_M_D_L =             10;
  35.       MAX_NR_SRC_FILES =      MAX_NR_FILE_SPECS;
  36.       MAX_NR_RSLT_MODULES =   10;
  37.       MAX_EXTR_MODE_L =       9;
  38.       MAX_FILE_EXT_L =        39;
  39.       MAX_OPTION_LENGTH =     15;
  40.       MAX_OPTIONS =           12;
  41.  
  42.   (*-----------   Constants to assist implemention of ADTs  -----------*)
  43.   CONST
  44.       MAX_NR_MESS =  35;
  45.       MAX_ERROR = 100;
  46.   CONST
  47.       EMPTY_OPTION = '               ';
  48.  
  49.   (*-----------   Global simple types of the CLiP system  -------------*)
  50.   TYPE
  51.       TO_BE_DECIDED_LATER_ =  (DEFINED,UNDEFINED);
  52.       LONGINTEGER =           -2147483647..2147483647;
  53.       STRING_FIXED_ =         PACKED ARRAY[1..STRING_FIXED_L] OF CHAR;
  54.       FILE_MODE_ =            (INSP_MODE, GEN_MODE);
  55.       SPECIAL_CHOICE_ =       CHAR;
  56.       ALLOWED_ANSW_ =         SET OF CHAR;
  57.       ERROR_MSG_ =            STRING_FIXED_;
  58.       SEV_CODE_ =             (WARN, ERR, FAIL, DUMP);
  59.       LOC_SPEC_ =             PACKED ARRAY[1..LOC_SPEC_L] OF CHAR;
  60.       FT_INDEX_ =             0..FT_SIZE;
  61.       ERROR_CODE_ =           INTEGER;
  62.       ST_INDEX_ =             -1..ST_SIZE;
  63.       SEGMENT_TYPE_ =         (STUB, SLOT, CODE, END_STUB);
  64.       SP_INDEX_ =             -1..SP_SIZE;
  65.       SYNTAX_STRING_ =        STRING_FIXED_;
  66.       MODE_ =                 STRING_FIXED_;
  67.       MESSAGE_DESTINATION_ =  STRING_FIXED_;
  68.       EXTR_MODE_ =            STRING_FIXED_;
  69.       FILE_EXT_ =             STRING_FIXED_;
  70.       CATEGORY_ =             (L1, L2, L3, L4, L5);
  71.       SLT_PTR_ =              ^SLOT_DES_;
  72.       STB_PTR_ =              ^STUB_DES_;
  73.       SHADOW_PTR_ =           ^SHADOW_LIST_;
  74.  
  75.   (*-----------   Global structured types of the CLiP system  ---------*)
  76.       STRING132_ =            RECORD
  77.                                   BODY:   STRING_FIXED_;
  78.                                   LENGTH: INTEGER;
  79.                               END (*RECORD*);
  80.       FILE_SPEC_ =            RECORD
  81.                                   LENGTH:  INTEGER;
  82.                                   BODY:    STRING_FIXED_;
  83.                               END (*RECORD*);
  84.       RSLT_MOD_SPEC_ =        RECORD
  85.                                   FILE_NAME: FILE_SPEC_;
  86.                                   PATH:      FILE_SPEC_;
  87.                               END (*RECORD*);
  88.       SOURCE_FILES_ =         ARRAY[1..MAX_NR_SRC_FILES] OF FILE_SPEC_;
  89.       RSLT_MODULES_ =         ARRAY[1..MAX_NR_RSLT_MODULES] OF
  90.                                                           RSLT_MOD_SPEC_;
  91.       FILE_SPECS_ =           RECORD
  92.                                   NR_FILE_SPECS: INTEGER;
  93.                                   FILES: SOURCE_FILES_;
  94.                               END (*RECORD*);
  95.       LINE_DES_ =             RECORD
  96.                                   CHARS:             STRING_FIXED_;
  97.                                   INDENT:            INTEGER;
  98.                                   USED:              INTEGER;
  99.                                   ID:                INTEGER;
  100.                                   POS_OPTION_MARKER: INTEGER;
  101.                               END (*RECORD*);
  102.       SEGMENT_DES_ =          RECORD
  103.                                   FIRST:    ST_INDEX_;
  104.                                   LAST:     ST_INDEX_;
  105.                               END (*RECORD*);
  106.       STRING_DES_ =           RECORD
  107.                                   FIRST:  SP_INDEX_;
  108.                                   LAST:   SP_INDEX_;
  109.                               END (*RECORD*);
  110.       SYNTAX_ =               RECORD
  111.                                   BODY:   SYNTAX_STRING_;
  112.                                   LENGTH: INTEGER;
  113.                               END (*RECORD*);
  114.       RUN_INFO_ = RECORD
  115.                       CLIP_LPAR,
  116.                       CLIP_RPAR:            SYNTAX_;
  117.                       CLIP_CC:              CHAR;
  118.                       CLIP_END:             SYNTAX_;
  119.                       OPTION_MARKER:        CHAR;
  120.                       MODE:                 MODE_;
  121.                       INT_FAULT_CORR:       BOOLEAN;
  122.                       MESSAGE_DESTINATION:  MESSAGE_DESTINATION_;
  123.                       REPORT_FILE_SPEC:     FILE_SPEC_;
  124.                       NR_SRC_FILES:         INTEGER;
  125.                       SOURCE_FILES:         SOURCE_FILES_;
  126.                       EXTR_MODE:            EXTR_MODE_;
  127.                       NR_MODULES:           INTEGER;
  128.                       RSLT_MODULES:         RSLT_MODULES_;
  129.                       DFLT_EXT:             FILE_EXT_;
  130.                       MODULE_DIRECTORY:     FILE_SPEC_;
  131.                   END (*RECORD*);
  132.       LINE_INFO_ =            RECORD
  133.                                   LINE_ID:    STRING_DES_;
  134.                                   CATEGORY:   CATEGORY_;
  135.                                   OPTIONS:    BOOLEAN;
  136.                               END (*RECORD*);
  137.       OPTIONS_  =             RECORD
  138.                                   QUICK,  MULTIPLE, OPTIONAL,  OVERRULE,
  139.                                   LEADER, TRAILER,  SEPARATOR, DEFAULT,
  140.                                   LINENUMBER:                     BOOLEAN;
  141.                                   INDENT,
  142.                                   FILE_NAME,
  143.                                   COMMENT:                        STRING_DES_;
  144.                               END (*RECORD*);
  145.       STUB_DES_ =             RECORD
  146.                                   NAME:       STRING_DES_ ;
  147.                                   SRC_IMG:    SEGMENT_DES_;
  148.                                   OPTIONS:    OPTIONS_    ;
  149.                                   SLOTS:      SLT_PTR_    ;
  150.                                   NEXT_TWIN,
  151.                                   NEXT_STUB:  STB_PTR_    ;
  152.                                   VISITED:    BOOLEAN     ;
  153.                               END (*RECORD*);
  154.       SLOT_DES_ =             RECORD
  155.                                   NAME:       STRING_DES_;
  156.                                   SRC_IMG:    SEGMENT_DES_;
  157.                                   OPTIONS:    OPTIONS_;
  158.                                   STUB_REF:   STB_PTR_;
  159.                                   CODE:       SEGMENT_DES_;
  160.                                   NEXT_SLOT:  SLT_PTR_;
  161.                               END (*RECORD*);
  162.       CODE_STRUCT_ =          RECORD
  163.                                   FIRST_STUB: STB_PTR_;
  164.                                   LAST_STUB:  STB_PTR_;
  165.                               END (*RECORD*);
  166.       SHADOW_LIST_ =          RECORD
  167.                                   STUB_POINTER:   STB_PTR_;
  168.                                   NEXT:           SHADOW_PTR_;
  169.                               END (*RECORD*);
  170.  
  171.   (*-----------   Types to assist implemention of ADTs  ---------------*)
  172.   TYPE
  173.       SP_TYPE =   RECORD
  174.                        CHARS: ARRAY[1..SP_SIZE] OF CHAR;
  175.                        USED : SP_INDEX_;
  176.                    END (*RECORD*);
  177.       SP_PTR =     ^SP_TYPE;
  178.   TYPE
  179.       OPTION_KEYWORD_ =   PACKED ARRAY [1..MAX_OPTION_LENGTH] OF CHAR;
  180.  
  181.   (*-----------   Global variables of the CLiP system  ----------------*)
  182.   VAR
  183.       REPORT_FILE:    TEXT;
  184.       REPORT_OK:      BOOLEAN;
  185.  
  186.   (*-----------   Variables to assist implemention of ADTs  -----------*)
  187.   VAR
  188.       START, STOP:    LONGINTEGER;
  189.       CONTINUE:       BOOLEAN;
  190.       RUN_INFO:       RUN_INFO_;
  191.       CODE_STRUCT:    CODE_STRUCT_;
  192.       (* STRING132:      STRING132_;   22/10/93  *)
  193.       (* DUMMY_LINE:     LINE_DES_;    22/10/93  *)
  194.       (* DUMMY_SEG:      SEGMENT_DES_; 22/10/93  *)
  195.       DUMMY_ERROR:    INTEGER;
  196.       INI_FILE:           TEXT;
  197.       EXT_FILE_SPEC:      FILE_SPEC_;
  198.       DUMMY_FILE_OK:      BOOLEAN;
  199.       DUMMY_ERROR_MSG:    ERROR_MSG_;
  200.       DUMMY_ERROR_CODE:   INTEGER;
  201.       ERROR_CODE:         ERROR_CODE_;
  202.       AUX_STRING_8:       PACKED ARRAY[1..8] OF CHAR;
  203.       I:                  INTEGER;
  204.           ERROR_MSG : ERROR_MSG_;
  205.   VAR
  206.       FILE_TABLE: ARRAY[1..FT_SIZE] OF RECORD
  207.                       FILE_SPEC:  FILE_SPEC_;
  208.                       FIRST:      INTEGER;
  209.                       LAST:       INTEGER;
  210.                   END (*RECORD*);
  211.       LAST_LINE:  INTEGER;
  212.       LAST_FILE:  FT_INDEX_;
  213.       CURR_IN_FILE:   TEXT;
  214.       CURR_OUT_FILE:  TEXT;
  215.       SPACE:             SET OF CHAR;
  216.   VAR
  217.       SEGMENT_TABLE:  RECORD
  218.                           LINES: ARRAY [1..ST_SIZE] OF LINE_DES_;
  219.                           USED:  ST_INDEX_;
  220.                       END (*RECORD*);
  221.       LAST_READ_SEG:  RECORD
  222.                           LAST_SEG:  SEGMENT_DES_;
  223.                           LAST_LINE: ST_INDEX_;
  224.                       END (*RECORD*);
  225.   VAR
  226.       STRING_POOL: SP_PTR;
  227.       BUFFER:      STRING132_;
  228.   VAR
  229.       DIAG_TBL:   ARRAY[1..MAX_NR_MESS] OF
  230.                       RECORD
  231.                           MESSAGE:        STRING_FIXED_;
  232.                           MESS_LOC:       LOC_SPEC_;
  233.                           MESS_L:         INTEGER;
  234.                       END (*RECORD*);
  235.       NO_MESSAGES:    BOOLEAN;
  236.       MSG_TBL:    ARRAY[1..MAX_ERROR+1] OF
  237.                       RECORD
  238.                           SEV:            SEV_CODE_;
  239.                           LOC:            LOC_SPEC_;
  240.                           SOURCE_LINE:    LINE_DES_;
  241.                           SEGMENT:        SEGMENT_DES_;
  242.                           STRING132:      STRING132_;
  243.                           LINE_ABS:       INTEGER;
  244.                       END (*RECORD*);
  245.       NR_MSG:     INTEGER;
  246.   VAR
  247.       ALLOWED:        SET OF CHAR;
  248.   VAR
  249.       OPTION_TABLE:       ARRAY [1..MAX_OPTIONS] OF OPTION_KEYWORD_;
  250.       OPT_SPACE:          SET OF CHAR;
  251.       OPT_CHARS:          SET OF CHAR;
  252.       DEFAULT_OPTIONS:    OPTIONS_;
  253.       PASCAL_STRING:      STRING_FIXED_;
  254.       FORTRAN_STRING:     STRING_FIXED_;
  255.       C_STRING:           STRING_FIXED_;
  256.  
  257.   (*-----------   Forward declarations  -------------------------------*)
  258.   PROCEDURE CLIP_STOP; FORWARD;
  259.   PROCEDURE EXT_FILE_CLOSE( VAR FILE_VAR  : TEXT;
  260.                             VAR ERROR_CODE: INTEGER);   FORWARD;
  261.   PROCEDURE EXT_FILE_PREP (VAR FILE_VAR:     TEXT;
  262.                            EXT_FILE_SPEC:    FILE_SPEC_;
  263.                            FILE_MODE:        FILE_MODE_;
  264.                            VAR FILE_OK:      BOOLEAN;
  265.                            VAR ERROR_CODE:   INTEGER;
  266.                            VAR ERROR_MSG:    ERROR_MSG_ );
  267.                                                                  FORWARD;
  268.   PROCEDURE READ_FILE_SPEC (VAR AUX_FILE_SPEC: FILE_SPEC_;
  269.                             VAR FILE_SPEC_OK:  BOOLEAN);
  270.                                                                  FORWARD;
  271.   PROCEDURE UC_WORD (VAR STR:  PACKED ARRAY [ONE..LEN:INTEGER]
  272.                                     OF CHAR);                FORWARD;
  273.   PROCEDURE WRITE_STRING (VAR OUT_FILE:   TEXT;
  274.                                    OUT_STRING: STRING_FIXED_;
  275.                                    NR_CHARS:   INTEGER);     FORWARD;
  276.   PROCEDURE WRLN_STRING (VAR OUT_FILE:   TEXT;
  277.                                   OUT_STRING: STRING_FIXED_;
  278.                                   NR_CHARS:   INTEGER;
  279.                                   SPACE:      INTEGER);      FORWARD;
  280.   FUNCTION  CHECK_SYNTAX (LPAR, RPAR, END_STRING: SYNTAX_;
  281.                           CC, MARKER:             CHAR): BOOLEAN;
  282.                                                                  FORWARD;
  283.   PROCEDURE INIT_RUN_INFO (VAR INIT_INFO: RUN_INFO_);
  284.                                                                  FORWARD;
  285.   PROCEDURE READ_INI_FILE (VAR INI_FILE:      TEXT;
  286.                            VAR READ_INFO:     RUN_INFO_;
  287.                            EXT_FILE_SPEC:     FILE_SPEC_;
  288.                            VAR FILE_OK:       BOOLEAN;
  289.                            VAR ERROR_MSG:     ERROR_MSG_;
  290.                            VAR ERROR_CODE:    INTEGER);
  291.                                                                  FORWARD;
  292.   PROCEDURE READ_LINE_SAFELY (VAR FILE_IN: TEXT);
  293.                                                                  FORWARD;
  294.   PROCEDURE READ_STRING (VAR IN_FILE:       TEXT;
  295.                          VAR IN_STR_LN:     INTEGER;
  296.                          VAR IN_STR_BODY:   STRING_FIXED_;
  297.                          NR_CHARS_TO_READ:  INTEGER);
  298.                                                                  FORWARD;
  299.   FUNCTION  UC (INCHAR: CHAR): CHAR;
  300.                                                                  FORWARD;
  301.   PROCEDURE VAL_INI_DATA (VAR VAL_INFO: RUN_INFO_;
  302.                           VAR OK:       BOOLEAN);
  303.                                                                  FORWARD;
  304.   FUNCTION  FT_ABS_LINE_NUMBER (SOURCE_LINE: LINE_DES_): INTEGER;
  305.                                                                  FORWARD;
  306.   FUNCTION  FT_CHECK_FILE (FILE_SPEC: FILE_SPEC_): ERROR_CODE_;
  307.                                                                  FORWARD;
  308.   FUNCTION  FT_EOF: BOOLEAN;
  309.                                                                  FORWARD;
  310.   FUNCTION  FT_GET_CHAR (SOURCE_LINE: LINE_DES_; INDEX: INTEGER): CHAR;
  311.                                                                  FORWARD;
  312.   PROCEDURE FT_GET_FILE_SPEC
  313.                       (SOURCE_LINE:LINE_DES_; VAR FILE_SPEC:FILE_SPEC_);
  314.                                                                  FORWARD;
  315.   FUNCTION  FT_GET_INDENT (SOURCE_LINE: LINE_DES_): INTEGER;
  316.                                                                  FORWARD;
  317.   FUNCTION  FT_GET_LINE_LENGTH (SOURCE_LINE: LINE_DES_): INTEGER;
  318.                                                                  FORWARD;
  319.   FUNCTION  FT_GET_LINE_NUMBER (SOURCE_LINE: LINE_DES_): INTEGER;
  320.                                                                  FORWARD;
  321.   FUNCTION  FT_GET_POS_OPTION_MARKER (SOURCE_LINE: LINE_DES_): INTEGER;
  322.                                                                  FORWARD;
  323.   FUNCTION  FT_INCLOSE: ERROR_CODE_;
  324.                                                                  FORWARD;
  325.   PROCEDURE FT_INIT;
  326.                                                                  FORWARD;
  327.   PROCEDURE FT_INIT_LINE (VAR LINE: LINE_DES_);
  328.                                                                  FORWARD;
  329.   FUNCTION  FT_INOPEN (FILE_SPEC: FILE_SPEC_): ERROR_CODE_;
  330.                                                                  FORWARD;
  331.   FUNCTION  FT_OUTOPEN (FILE_SPEC: FILE_SPEC_): ERROR_CODE_;
  332.                                                                  FORWARD;
  333.   FUNCTION  FT_OUTCLOSE: ERROR_CODE_;
  334.                                                                  FORWARD;
  335.   PROCEDURE FT_RDLN (VAR LINE: LINE_DES_);
  336.                                                                  FORWARD;
  337.   PROCEDURE FT_WRLN (VAR LINE: LINE_DES_; NR_BLANKS:   INTEGER;
  338.                                           DESTINATION: INTEGER);
  339.                                                                  FORWARD;
  340.   FUNCTION  ST_ABS_SEG (SEGMENT: SEGMENT_DES_):INTEGER;
  341.                                                                  FORWARD;
  342.   PROCEDURE ST_GET_FILE_SPEC (    SEGMENT: SEGMENT_DES_;
  343.                               VAR FILE_SPEC: FILE_SPEC_);
  344.                                                                  FORWARD;
  345.   FUNCTION  ST_GET_INDENT (SEG: SEGMENT_DES_): INTEGER;
  346.                                                                  FORWARD;
  347.   PROCEDURE ST_GET_LINE (VAR LINE: LINE_DES_);
  348.                                                                  FORWARD;
  349.   PROCEDURE ST_GET_OPTION_LINE (SEG: SEGMENT_DES_; VAR LINE: LINE_DES_);
  350.                                                                  FORWARD;
  351.   PROCEDURE ST_GET_SEG (SEG: SEGMENT_DES_; VAR LINE: LINE_DES_);
  352.                                                                  FORWARD;
  353.   PROCEDURE ST_GET_SEG_RANGE (    SEGMENT: SEGMENT_DES_;
  354.                               VAR FIRST, LAST:INTEGER);
  355.                                                                  FORWARD;
  356.   PROCEDURE ST_INIT;
  357.                                                                  FORWARD;
  358.   PROCEDURE ST_INIT_SEG  (VAR SEG: SEGMENT_DES_);
  359.                                                                  FORWARD;
  360.   FUNCTION  ST_IS_EMPTY_SEG (SEG: SEGMENT_DES_): BOOLEAN;
  361.                                                                  FORWARD;
  362.   FUNCTION  ST_NUMBER_OF_LINES (SEG: SEGMENT_DES_): INTEGER;
  363.                                                                  FORWARD;
  364.   PROCEDURE ST_PUT_LINE (LINE: LINE_DES_; VAR SEG: SEGMENT_DES_);
  365.                                                                  FORWARD;
  366.   PROCEDURE ST_PUT_SEG (LINE: LINE_DES_; VAR SEG: SEGMENT_DES_);
  367.                                                                  FORWARD;
  368.   PROCEDURE ST_FINIT;
  369.                                                                  FORWARD;
  370.   FUNCTION  ST_SEG_WIDTH (SEG: SEGMENT_DES_): INTEGER;
  371.                                                                  FORWARD;
  372.   PROCEDURE ST_WRITE_SEG (SEG: SEGMENT_DES_; BLANKS:      INTEGER;
  373.                                              DESTINATION: INTEGER);
  374.                                                                  FORWARD;
  375.   PROCEDURE SP_ADD_CHAR (CH: CHAR; VAR STR: STRING_DES_);
  376.                                                                  FORWARD;
  377.   PROCEDURE SP_CONC_STR (VAR MASTER: STRING_DES_; SLAVE: STRING_DES_);
  378.                                                                  FORWARD;
  379.   FUNCTION  SP_EQ (STR1: STRING_DES_; STR2: STRING_DES_): BOOLEAN;
  380.                                                                  FORWARD;
  381.   PROCEDURE SP_EXTR_STR (STR: STRING_DES_; VAR STR132: STRING132_);
  382.                                                                  FORWARD;
  383.   FUNCTION  SP_GET_CHAR (INDEX: INTEGER; STR: STRING_DES_): CHAR;
  384.                                                                  FORWARD;
  385.   PROCEDURE SP_INIT;
  386.                                                                  FORWARD;
  387.   PROCEDURE SP_INIT_STR (VAR STR: STRING_DES_);
  388.                                                                  FORWARD;
  389.   FUNCTION  SP_IS_EMPTY_STR (STR: STRING_DES_): BOOLEAN;
  390.                                                                  FORWARD;
  391.   FUNCTION  SP_LENGTH_STR (STR: STRING_DES_): INTEGER;
  392.                                                                  FORWARD;
  393.   PROCEDURE SP_ADD_BUFFER (VAR STR: STRING_DES_);
  394.                                                                  FORWARD;
  395.   PROCEDURE SP_ADD_BUFFER_CHAR (CH: CHAR);
  396.                                                                  FORWARD;
  397.   FUNCTION  SP_GET_BUFFER_CHAR (INDEX: INTEGER): CHAR;
  398.                                                                  FORWARD;
  399.   PROCEDURE SP_INIT_BUFFER;
  400.                                                                  FORWARD;
  401.  
  402.   (*-----------   General routines  -----------------------------------*)
  403.  
  404.   (*********************************************************************)
  405.   (* Procedure:   CLIP_STOP (VAX-version)                              *)
  406.   (* Purpose:     To halt a program without any message or dump.       *)
  407.   (*********************************************************************)
  408.   PROCEDURE CLIP_STOP;
  409.   BEGIN
  410.   HALT
  411.   END (*PROCEDURE CLIP_STOP*);
  412.  
  413.   (*********************************************************************)
  414.   (* Routine:     EXT_FILE_CLOSE (VAX-version)                         *)
  415.   (* Purpose:     To close an external file.                           *)
  416.   (* Interface:   FILE_VAR      - Pascal file in question              *)
  417.   (*              ERROR_CODE    - Error indication to caller           *)
  418.   (*********************************************************************)
  419.   PROCEDURE EXT_FILE_CLOSE;
  420.   BEGIN
  421.       CLOSE (FILE_VAR);
  422.       ERROR_CODE := 0;
  423.   END (*EXT_FILE_CLOSE*);
  424.  
  425.   (*********************************************************************)
  426.   (* Procedure:     EXT_FILE_PREP ( VAX-version )                      *)
  427.   (* Purpose:       To prepare an external file for reading from it    *)
  428.   (*                or writing to it.                                  *)
  429.   (* Interface:     EXT_FILE_SPEC - VMS-file in question.              *)
  430.   (*                FILE_MODE -     Mode indicator.                    *)
  431.   (*                FILE_VAR -      Pascal file in question.           *)
  432.   (*                FILE_OK  -      Indicates succesfull preparation.  *)
  433.   (*                ERROR_CODE -    Error indication to caller.        *)
  434.   (*                ERROR_MSG  -    Error message to caller.           *)
  435.   (*********************************************************************)
  436.   PROCEDURE EXT_FILE_PREP;
  437.   VAR
  438.       AUX_FILE_SPEC:  VARYING [MAX_FILE_SPEC_L] OF CHAR;
  439.   BEGIN
  440.       ERROR_CODE := -1;                     (* Initialization      *)
  441.           AUX_FILE_SPEC := EXT_FILE_SPEC.BODY;
  442.       IF (FILE_MODE = INSP_MODE) THEN
  443.       BEGIN
  444.           IF (EXT_FILE_SPEC.LENGTH <> 0) THEN
  445.           BEGIN
  446.               (* First the file has to be opened.                  *)
  447.               OPEN (FILE_VAR,
  448.                     AUX_FILE_SPEC,
  449.                     'old',
  450.                     ERROR_CODE);
  451.               IF ERROR_CODE = 0 THEN
  452.                   RESET (FILE_VAR);
  453.           END (*IF*);
  454.       END
  455.       ELSE
  456.       BEGIN
  457.           (* FILE_MODE is gelijk aan GEN_MODE                      *)
  458.           IF (EXT_FILE_SPEC.LENGTH <> 0) THEN
  459.           BEGIN
  460.               (* First the file has to be opened.                  *)
  461.               OPEN (FILE_VAR,
  462.                     AUX_FILE_SPEC,
  463.                     'unknown',
  464.                     ERROR_CODE);
  465.               IF ERROR_CODE = 0 THEN
  466.                   REWRITE (FILE_VAR);
  467.           END (*IF*);
  468.       END (*IF*);
  469.     
  470.       (* DEFAULT CODE: *)
  471.       IF NOT (ERROR_CODE = 0) THEN
  472.       BEGIN
  473.           FILE_OK := FALSE;
  474.           (* This string is a bit too short for the assignment,    *)
  475.           (* but that is no problem in VAX-Pascal.                 *)
  476.           CASE ERROR_CODE OF
  477.              -1:  BEGIN
  478.                       ERROR_MSG := 'Empty file name.';
  479.                   END;
  480.               2:  BEGIN
  481.                       ERROR_MSG := 'File not found.';
  482.                   END;
  483.               OTHERWISE
  484.                   ERROR_MSG := 'Unsuccesful performance';
  485.           END (*CASE*);
  486.       END (*IF*)
  487.       ELSE
  488.       BEGIN
  489.           FILE_OK    := TRUE;
  490.           ERROR_MSG  := 'Succesful performance. ';
  491.           ERROR_CODE := 0;
  492.       END (*IF*);
  493.       (* END DEFAULT CODE *)
  494.     
  495.   END (*EXT_FILE_PREP*);
  496.  
  497.   (*********************************************************************)
  498.   (* Procedure:   READ_FILE_SPEC                                       *)
  499.   (* Purpose:     To read a filespecification from the terminal.       *)
  500.   (* Interface:   AUX_FILE_SPEC - Returned file specification.         *)
  501.   (*              FILE_SPEC_OK -  File specification from terminal.    *)
  502.   (* Author/Date: Maarten Rooda, January 1991.                         *)
  503.   (*********************************************************************)
  504.   PROCEDURE READ_FILE_SPEC;
  505.   VAR
  506.       VAX_AUX_FILE_SPEC:  VARYING [MAX_FILE_SPEC_L] OF CHAR;
  507.       I:                  INTEGER;  (* loopvariable.                   *)
  508.           DUMMY_FILE: TEXT;
  509.           FILE_OK:    BOOLEAN;
  510.           ERROR_CODE: INTEGER;
  511.           ERROR_MSG:  ERROR_MSG_;
  512.  
  513.   BEGIN
  514.       FILE_SPEC_OK := TRUE;
  515.       READLN (VAX_AUX_FILE_SPEC);
  516.       FOR I := 1 TO LENGTH(VAX_AUX_FILE_SPEC) DO
  517.       BEGIN
  518.           AUX_FILE_SPEC.BODY[I] := VAX_AUX_FILE_SPEC[I];
  519.       END (*FOR*);
  520.       AUX_FILE_SPEC.LENGTH := LENGTH(VAX_AUX_FILE_SPEC)
  521.   END (*PROCEDURE READ_FILE_SPEC*);
  522.  
  523.   (*********************************************************************)
  524.   (* Routine:    UC_WORD                                               *)
  525.   (* Pupose:     To convert a string to upper case .                   *)
  526.   (* Interface:  STRING -   String to be converted                     *)
  527.   (*********************************************************************)
  528.   PROCEDURE UC_WORD;
  529.   VAR
  530.       COUNTER: INTEGER;
  531.   BEGIN
  532.       FOR COUNTER := ONE TO LEN DO
  533.           STR[COUNTER] := UC (STR[COUNTER]);
  534.   END (*UC_WORD*);
  535.  
  536.   (*********************************************************************)
  537.   (* Procedure:   WRITE_STRING (VAX-version)                           *)
  538.   (* Purpose:     Write a part of a text string to a text file         *)
  539.   (* Interface:   OUT_FILE   - The file that is written to             *)
  540.   (*              NR_CHARS   - The number of CHAR's that have to be    *)
  541.   (*                           written to the file                     *)
  542.   (*              OUT_STRING - The string to be written                *)
  543.   (* Author/date: Hans Rabouw, March 1992                              *)
  544.   (*********************************************************************)
  545.   PROCEDURE WRITE_STRING;
  546.   VAR
  547.       I: INTEGER;
  548.   BEGIN
  549.       FOR I:= 1 TO NR_CHARS DO
  550.           WRITE(OUT_FILE, OUT_STRING[I]);
  551.   END;
  552.  
  553.   (*********************************************************************)
  554.   (* Routine:     WRLN_STRING - WRiTeLN STRING. (VAX-version)          *)
  555.   (* Purpose:     Write a part of a text string to a text file and     *)
  556.   (*              jump to the next line in the file after that.        *)
  557.   (* Interface:   OUT_FILE   - The file that is written to             *)
  558.   (*              NR_CHARS   - The number of CHAR's that have to be    *)
  559.   (*                           written to the file                     *)
  560.   (*              OUT_STRING - The string to be written                *)
  561.   (*              SPACE      - Number of spaces written before string. *)
  562.   (* Author/date: Heleen Hollenberg, june 1992.                        *)
  563.   (*********************************************************************)
  564.   PROCEDURE WRLN_STRING;
  565.   VAR
  566.       I: INTEGER;
  567.   BEGIN
  568.       FOR I := 1 TO SPACE DO
  569.           WRITE (OUT_FILE, ' ' );
  570.       FOR I:= 1 TO NR_CHARS DO
  571.           WRITE (OUT_FILE, OUT_STRING[I]);
  572.       WRITELN (OUT_FILE);
  573.   END;
  574.  
  575.   (*********************************************************************)
  576.   (* Routine:     READ_LINE_SAFELY                                     *)
  577.   (* Purpose:     To read a line from a file .                         *)
  578.   (* Interface:   FILE_IN -   File to be read                          *)
  579.   (* Author/date: Boudewijn Pelt, August 1991.                         *)
  580.   (*********************************************************************)
  581.   PROCEDURE READ_LINE_SAFELY;
  582.   BEGIN
  583.       IF NOT EOF (FILE_IN) THEN
  584.           READLN (FILE_IN);
  585.   END (*READ_LINE_SAFELY*);
  586.  
  587.   (*********************************************************************)
  588.   (* Routine:     CHECK_SYNTAX                                         *)
  589.   (* Purpose:     To check the syntax parameters of CLIP. If they are  *)
  590.   (*              not legal then the function result is FALSE          *)
  591.   (* Interface:   LPAR -          CLIP Left parenthesis definition     *)
  592.   (*              RPAR -          CLIP Right parenthesis definition    *)
  593.   (*              END_STRING -    End of stub indicator                *)
  594.   (*              CC -            CLIP Control Character               *)
  595.   (*              MARKER -                                             *)
  596.   (*              CHECK_SYNTAX -  Show example of CLIP-syntax          *)
  597.   (* Author/date: Boudewijn Pelt, July 1991                            *)
  598.   (*********************************************************************)
  599.   FUNCTION CHECK_SYNTAX;
  600.   VAR
  601.       COUNTER:  INTEGER;
  602.       ERROR:    BOOLEAN;
  603.  
  604.   BEGIN
  605.       ERROR := FALSE;
  606.       FOR COUNTER := 1 TO SYNTAX_LEN DO
  607.           IF MARKER IN [LPAR.BODY[COUNTER], RPAR.BODY[COUNTER],
  608.                         END_STRING.BODY[COUNTER]] THEN
  609.               ERROR := TRUE;
  610.       IF MARKER = CC THEN
  611.           ERROR := TRUE;
  612.  
  613.       IF LPAR.BODY[LPAR.LENGTH] <> CC THEN
  614.           ERROR := TRUE;
  615.       IF RPAR.BODY[1] <> CC THEN
  616.           ERROR := TRUE;
  617.  
  618.       WITH LPAR DO
  619.       BEGIN
  620.           IF LENGTH <= 1 THEN
  621.               ERROR := TRUE;
  622.           FOR COUNTER := 1 TO LENGTH DO
  623.               IF BODY[COUNTER] IN ALLOWED_ID_CHARS THEN
  624.                   ERROR := TRUE;
  625.       END (*WITH*);
  626.       WITH RPAR DO
  627.       BEGIN
  628.           IF LENGTH <= 1 THEN
  629.               ERROR := TRUE;
  630.           FOR COUNTER := 1 TO LENGTH DO
  631.               IF BODY[COUNTER] IN ALLOWED_ID_CHARS THEN
  632.                   ERROR := TRUE;
  633.       END (*WITH*);
  634.       WITH END_STRING DO
  635.       BEGIN
  636.           IF LENGTH <= 0 THEN
  637.               ERROR := TRUE;
  638.           FOR COUNTER := 1 TO LENGTH DO
  639.               IF NOT (BODY[COUNTER] IN ALLOWED_ID_CHARS) THEN
  640.                   ERROR := TRUE;
  641.       END (*WITH*);
  642.       IF (CC IN ALLOWED_ID_CHARS) OR (CC = ' ') THEN
  643.           ERROR := TRUE;
  644.       IF (MARKER IN ALLOWED_ID_CHARS) OR (MARKER = ' ') THEN
  645.           ERROR := TRUE;
  646.  
  647.       CHECK_SYNTAX :=  NOT ERROR;
  648.   END (*CHECK_SYNTAX*);
  649.  
  650.   (*********************************************************************)
  651.   (* Procedure:   INIT_RUN_INFO .                                      *)
  652.   (* Purpose:     To initialize the fields of a record INIT_INFO of    *)
  653.   (*              type RUN_INFO_ to default values.                    *)
  654.   (* Interface:   INIT_INFO - Structure to initialize.                 *)
  655.   (* Author/date: Maarten Rooda, January 1991.                         *)
  656.   (*********************************************************************)
  657.   PROCEDURE INIT_RUN_INFO;
  658.  
  659.   CONST
  660.       AUX_STR_L = MAX_MODE_L;
  661.  
  662.   VAR
  663.       I:    INTEGER;
  664.       AUX_STRING: PACKED ARRAY[1..AUX_STR_L] OF CHAR;
  665.  
  666.   BEGIN
  667.       (*******                INIT_RUN_INFO body                     *******)
  668.       WITH INIT_INFO DO
  669.       BEGIN
  670.           (* additional parameters of init_info.                           *)
  671.           CLIP_LPAR.BODY := EMPTY_STRING_FIXED;
  672.           CLIP_LPAR.BODY[1] := '(';
  673.           CLIP_LPAR.BODY[2] := '*';
  674.           CLIP_LPAR.BODY[3] := '*';
  675.           CLIP_LPAR.LENGTH := 3;
  676.     
  677.           CLIP_RPAR.BODY := EMPTY_STRING_FIXED;
  678.           CLIP_RPAR.BODY[1] := '*';
  679.           CLIP_RPAR.BODY[2] := '*';
  680.           CLIP_RPAR.BODY[3] := ')';
  681.           CLIP_RPAR.LENGTH := 3;
  682.     
  683.           CLIP_END.BODY := EMPTY_STRING_FIXED;
  684.           CLIP_END.BODY[1] := 'E';
  685.           CLIP_END.BODY[2] := 'N';
  686.           CLIP_END.BODY[3] := 'D';
  687.           CLIP_END.BODY[4] := 'O';
  688.           CLIP_END.BODY[5] := 'F';
  689.           CLIP_END.LENGTH := 5;
  690.     
  691.           CLIP_CC := '*';
  692.           OPTION_MARKER := '#';
  693.     
  694.           (* old parameters.                                               *)
  695.           MODE := EMPTY_STRING_FIXED;
  696.           AUX_STRING := 'INTERACTIVE_MODE';
  697.           FOR I := 1 TO MAX_MODE_L DO
  698.               MODE[I] := AUX_STRING[I];
  699.     
  700.           INT_FAULT_CORR := TRUE;
  701.     
  702.           MESSAGE_DESTINATION := EMPTY_STRING_FIXED;
  703.           AUX_STRING := 'TERMINAL        ';
  704.           FOR I := 1 TO MAX_M_D_L DO
  705.               MESSAGE_DESTINATION[I] := AUX_STRING[I];
  706.     
  707.           REPORT_FILE_SPEC.BODY := EMPTY_STRING_FIXED;
  708.           REPORT_FILE_SPEC.BODY[1] := 'C';
  709.           REPORT_FILE_SPEC.BODY[2] := 'L';
  710.           REPORT_FILE_SPEC.BODY[3] := 'I';
  711.           REPORT_FILE_SPEC.BODY[4] := 'P';
  712.           REPORT_FILE_SPEC.BODY[5] := '.';
  713.           REPORT_FILE_SPEC.BODY[6] := 'R';
  714.           REPORT_FILE_SPEC.BODY[7] := 'P';
  715.           REPORT_FILE_SPEC.BODY[8] := 'T';
  716.           REPORT_FILE_SPEC.LENGTH := 8;
  717.     
  718.           NR_SRC_FILES := 0;
  719.     
  720.           (* Default:                                                      *)
  721.           EXTR_MODE := EMPTY_STRING_FIXED;
  722.           AUX_STRING := 'OMITTED         ';
  723.           FOR I := 1 TO MAX_EXTR_MODE_L DO
  724.               EXTR_MODE[I] := AUX_STRING[I];
  725.     
  726.           NR_MODULES:= 0;
  727.           MODULE_DIRECTORY.BODY := EMPTY_STRING_FIXED;
  728.           MODULE_DIRECTORY.LENGTH := 0;
  729.     
  730.       END (* WITH INIT_INFO *);
  731.       (*****************  End of INIT_RUN_INFO body  ***********************)
  732.   END (*INIT_RUN_INFO*);
  733.  
  734.   (*********************************************************************)
  735.   (* Procedure:   READ_INI_FILE                                        *)
  736.   (* Purpose:     To open an initializationfile and read data from     *)
  737.   (*              it into a record READ_INFO of type RUN_INFO_ .       *)
  738.   (* Interface:   INI_FILE:      The initializationfile in question.   *)
  739.   (*              READ_INFO:     Information for a run of CLIP.        *)
  740.   (*              EXT_FILE_SPEC: The filespecification                 *)
  741.   (*              FILE_OK:       TRUE if data read successfully        *)
  742.   (*              ERROR_MSG:     Error message.                        *)
  743.   (*              ERROR_CODE:    Type of error.                        *)
  744.   (* Author/date: Maarten Rooda, February 1991.                        *)
  745.   (*********************************************************************)
  746.   PROCEDURE READ_INI_FILE;
  747.   VAR
  748.       DUMMY_CODE: INTEGER;
  749.  
  750.   (*********************************************************************)
  751.   (* Procedure:   READ_INI_DATA                                        *)
  752.   (* Purpose:     To read data from an initializationfile into a       *)
  753.   (*              record READ_INFO of type RUN_INFO_ .                 *)
  754.   (* Interface:   INI_FILE -  INI-file to be read                      *)
  755.   (*              READ_INFO - Structure to return the data.            *)
  756.   (* Author/date: Boudewijn Pelt, May 1991.                            *)
  757.   (*********************************************************************)
  758.   PROCEDURE READ_INI_DATA(VAR INI_FILE:  TEXT;
  759.                           VAR READ_INFO: RUN_INFO_);
  760.   CONST
  761.       SKIP_LINES = 5;
  762.   VAR
  763.       COUNTER:  INTEGER;
  764.       LETTER:  STRING_FIXED_;  (* This is an array that can be read by *)
  765.                                (* READ_STRING                          *)
  766.       DUMMY_L: INTEGER;        (* A dummy parameter for READ_STRING    *)
  767.       OK:  BOOLEAN;
  768.       AUX_STR_34 : PACKED ARRAY[1..34] OF CHAR;
  769.  
  770.  
  771.   (*********************************************************************)
  772.   (* Routine:     GET_SOURCE_FILES                                     *)
  773.   (* Purpose:     To read a number of filespecifications from an       *)
  774.   (*              input file.                                          *)
  775.   (* Interface:   FILE_IN -   File with data to be read                *)
  776.   (*              FILES -     Data of files                            *)
  777.   (*              NR_FILES -  Number of files                          *)
  778.   (* Author/date: Boudewijn Pelt, August 1991                          *)
  779.   (* Modified:    Hans Rabouw, March 1992                              *)
  780.   (*********************************************************************)
  781.   PROCEDURE GET_SOURCE_FILES
  782.                 (VAR FILE_IN:  TEXT;
  783.                  VAR FILES:    SOURCE_FILES_;
  784.                  VAR NR_FILES: INTEGER);
  785.   VAR
  786.       I:                INTEGER;
  787.       READ_ON:          BOOLEAN;
  788.       AUX_FILE_SPEC:    FILE_SPEC_;
  789.  
  790.   BEGIN
  791.       I := 0;
  792.       READ_ON := NOT (EOF (FILE_IN));
  793.       WHILE READ_ON DO
  794.       BEGIN
  795.           WITH AUX_FILE_SPEC DO
  796.               READ_STRING(FILE_IN, LENGTH, BODY, MAX_FILE_SPEC_L);
  797.           READ_LINE_SAFELY(INI_FILE);
  798.           IF (AUX_FILE_SPEC.BODY[1] = '-') OR
  799.              (AUX_FILE_SPEC.LENGTH = 0) THEN
  800.              (* AUX_FILE_SPEC was not read successfully.               *)
  801.               READ_ON := FALSE
  802.           ELSE IF I < MAX_NR_SRC_FILES THEN
  803.           BEGIN
  804.               (* AUX_FILE_SPEC was read successfully.                  *)
  805.               I := I + 1;
  806.               FILES[I] := AUX_FILE_SPEC;
  807.           END (*IF.IF*);
  808.       END (*WHILE*);
  809.       NR_FILES := I;
  810.   END (*GET_SOURCE_FILES*);
  811.  
  812.  
  813.   (*********************************************************************)
  814.   (* Routine:     GET_MODULES                                          *)
  815.   (* Purpose:     To read a number of filespecifications from an       *)
  816.   (*              input file.                                          *)
  817.   (* Interface:   FILE_IN -   File with data to be read                *)
  818.   (*              FILES -     Data of files                            *)
  819.   (*              NR_FILES -  Number of files                          *)
  820.   (* Author/date: Boudewijn Pelt, August 1991                          *)
  821.   (* Modified:    Hans Rabouw, March 1992                              *)
  822.   (*********************************************************************)
  823.   PROCEDURE GET_MODULES
  824.                 (VAR FILE_IN:  TEXT;
  825.                  VAR FILES:    RSLT_MODULES_;
  826.                  VAR NR_FILES: INTEGER);
  827.  
  828.   VAR
  829.       I:                INTEGER;
  830.       READ_ON:          BOOLEAN;
  831.       AUX_FILE_SPEC:    FILE_SPEC_;
  832.       AUX_PATH_SPEC:    FILE_SPEC_;
  833.  
  834.   BEGIN
  835.       I := 0;
  836.       READ_ON := NOT (EOF (FILE_IN));
  837.       WHILE READ_ON DO
  838.       BEGIN
  839.           WITH AUX_PATH_SPEC DO
  840.               READ_STRING(FILE_IN, LENGTH, BODY, MAX_FILE_SPEC_L);
  841.           READ_LINE_SAFELY(INI_FILE);
  842.           IF (AUX_PATH_SPEC.BODY[1] = '-')
  843.   (*          OR (AUX_PATH_SPEC.LENGTH = 0)    (EWvA nav. HR 17/11/92) *)
  844.           THEN
  845.              (* AUX_PATH_SPEC was not read successfully.               *)
  846.               READ_ON := FALSE
  847.           ELSE
  848.           BEGIN
  849.               WITH AUX_FILE_SPEC DO
  850.                     READ_STRING(FILE_IN, LENGTH, BODY, MAX_FILE_SPEC_L);
  851.               READ_LINE_SAFELY(INI_FILE);
  852.               IF (AUX_FILE_SPEC.BODY[1] = '-') OR
  853.                   (AUX_FILE_SPEC.LENGTH = 0) THEN
  854.                   READ_ON := FALSE
  855.               ELSE IF I < MAX_NR_RSLT_MODULES THEN
  856.               BEGIN
  857.                   (* AUX_FILE_SPEC was read successfully.                  *)
  858.                   I := I + 1;
  859.                   FILES[I].FILE_NAME := AUX_FILE_SPEC;
  860.                   FILES[I].PATH := AUX_PATH_SPEC;
  861.               END (*IF.IF*);
  862.           END (*IF*);
  863.       END (*WHILE*);
  864.       NR_FILES := I;
  865.   END (*GET_MODULES*);
  866.  
  867.  
  868.   BEGIN
  869.       (*******            READ_INI_DATA body                     *******)
  870.       RESET (INI_FILE);
  871.       FOR COUNTER := 1 TO SKIP_LINES DO
  872.           READ_LINE_SAFELY(INI_FILE);
  873.       WITH READ_INFO DO
  874.       BEGIN
  875.           (*********************  READ_INI_DATA (1)  ***********************)
  876.           (** Read the data from INI_FILE into MODE, INT_FAULT_CORR,      **)
  877.           (** MESSAGE_DESTINATION, REPORT_FILE_SPEC, CLIP_LPAR, CLIP_-    **)
  878.           (** RPAR, CLIP_CC, CLIP_END, OPTION_MARKER, NR_SCR_FILES,       **)
  879.           (** SOURCE_FILES, NR_MODULES, EXTR_MODE, RSLT_MODULES.          **)
  880.           READ_STRING(INI_FILE, DUMMY_L, MODE, MAX_MODE_L);
  881.           READ_LINE_SAFELY(INI_FILE);
  882.           READ_STRING(INI_FILE, DUMMY_L, LETTER, 1);
  883.           READ_LINE_SAFELY(INI_FILE);
  884.           INT_FAULT_CORR := LETTER[1] = 'Y';
  885.           READ_STRING(INI_FILE, DUMMY_L, MESSAGE_DESTINATION, MAX_M_D_L);
  886.           READ_LINE_SAFELY(INI_FILE);
  887.           WITH CLIP_LPAR DO
  888.               READ_STRING(INI_FILE, LENGTH, BODY, SYNTAX_LEN);
  889.         
  890.           READ_LINE_SAFELY(INI_FILE);
  891.           WITH CLIP_RPAR DO
  892.               READ_STRING(INI_FILE, LENGTH, BODY, SYNTAX_LEN);
  893.         
  894.           READ_LINE_SAFELY(INI_FILE);
  895.           READ_STRING(INI_FILE, DUMMY_L, LETTER, 1);
  896.           READ_LINE_SAFELY(INI_FILE);
  897.           CLIP_CC := LETTER[1];
  898.           WITH CLIP_END DO
  899.               READ_STRING(INI_FILE, LENGTH, BODY, SYNTAX_LEN);
  900.         
  901.           READ_LINE_SAFELY(INI_FILE);
  902.           READ_STRING(INI_FILE, DUMMY_L, LETTER, 1);
  903.           READ_LINE_SAFELY(INI_FILE);
  904.           OPTION_MARKER := LETTER[1];
  905.           READ_STRING(INI_FILE, DUMMY_L, EXTR_MODE, MAX_EXTR_MODE_L);
  906.         
  907.           READ_LINE_SAFELY(INI_FILE);
  908.         
  909.           (************************  READ_INI_DATA (1.1)  **********************)
  910.           (** Read the file specifications REPORT_FILE_SPEC,                  **)
  911.           (** SOURCE_FILES.FILES[1..NR_FILE_SPECS]                            **)
  912.           (** RSLT_MODULES.FILES[1..NR_FILE_SPECS] from the INI_FILE.         **)
  913.           READ_LINE_SAFELY(INI_FILE);               (* Skip -- REPORT FILE --  *)
  914.           WITH REPORT_FILE_SPEC DO
  915.               READ_STRING(INI_FILE, LENGTH, BODY, MAX_FILE_SPEC_L);
  916.         
  917.           READ_LINE_SAFELY(INI_FILE);
  918.           READ_LINE_SAFELY(INI_FILE);               (* skip -- INPUT FILES --  *)
  919.           GET_SOURCE_FILES (INI_FILE, SOURCE_FILES, NR_SRC_FILES);
  920.           GET_MODULES (INI_FILE, RSLT_MODULES, NR_MODULES);
  921.         
  922.           (* There is no need to skip the '--- MODULE DIRECTORY ---' line *)
  923.           (* because it is read by the GET_MODULES procedure              *)
  924.         
  925.           WITH MODULE_DIRECTORY DO
  926.               READ_STRING(INI_FILE, LENGTH, BODY, MAX_FILE_SPEC_L);
  927.         
  928.           (*****************  End of READ_INI_DATA (1.1)  **********************)
  929.         
  930.           (************************  READ_INI_DATA (1.2)  **********************)
  931.           (** CLIP_LPAR and CLIP_RPAR are not complete. An CLIP_CC needs to   **)
  932.           (** be added.                                                       **)
  933.           WITH CLIP_LPAR DO
  934.           BEGIN
  935.               IF LENGTH < SYNTAX_LEN THEN
  936.                   LENGTH := LENGTH + 1;
  937.               BODY[LENGTH] := CLIP_CC;
  938.           END (*WITH*);
  939.           WITH CLIP_RPAR DO
  940.           BEGIN
  941.               LENGTH := LENGTH + 1;
  942.               IF LENGTH > SYNTAX_LEN THEN
  943.                   LENGTH := SYNTAX_LEN;
  944.               FOR COUNTER := LENGTH-1 DOWNTO 1 DO
  945.                   BODY[COUNTER+1] := BODY[COUNTER];
  946.               BODY[1] := CLIP_CC;
  947.           END (*WITH*);
  948.           (******************  End of READ_INI_DATA (1.2)  *********************)
  949.         
  950.           (*****************  End of READ_INI_DATA (1)  ********************)
  951.       END (*WITH*);
  952.     
  953.       (*************************  READ_INI_DATA (2)  ***********************)
  954.       (** Check if READ_INFO is valid. If not display an error message    **)
  955.       (** and set READ_INFO to default values.                            **)
  956.       VAL_INI_DATA (READ_INFO, OK);
  957.       IF NOT OK THEN
  958.       BEGIN
  959.           (*********************  READ_INI_DATA (2.1)  *********************)
  960.           (** Generate a warning message                                  **)
  961.           ERROR_CODE := CORRUPT_INI_FILE;
  962.           ERROR_MSG := EMPTY_STRING_FIXED;
  963.           AUX_STR_34 := 'THE SPECIFIED INI-FILE IS CORRUPT.';
  964.           FOR COUNTER := 1 TO 34 DO
  965.               ERROR_MSG[COUNTER] := AUX_STR_34[COUNTER];
  966.           (*****************  End of READ_INI_DATA (2.1)  ******************)
  967.           INIT_RUN_INFO(READ_INFO);
  968.       END (*IF*);
  969.       (*********************  End of READ_INI_DATA (2)  ********************)
  970.     
  971.       (*****************  End of READ_INI_DATA body  ***********************)
  972.   END (*READ_INI_DATA*);
  973.  
  974.   BEGIN
  975.       FILE_OK := FALSE;
  976.       EXT_FILE_PREP(INI_FILE, EXT_FILE_SPEC, INSP_MODE, FILE_OK,
  977.                     ERROR_CODE, ERROR_MSG);
  978.       IF FILE_OK THEN
  979.       BEGIN
  980.           READ_INI_DATA (INI_FILE, READ_INFO);
  981.           (* If the INI-file contained an error, the READ_INFO record  *)
  982.           (* was initialized by READ_INI_DATA.                         *)
  983.           EXT_FILE_CLOSE (INI_FILE, DUMMY_CODE);     (* EWvA, 16/10/93 *)
  984.       END (*IF*);
  985.   END (*READ_INI_FILE*);
  986.  
  987.   (*********************************************************************)
  988.   (* Procedure:   READ_STRING                                          *)
  989.   (* Purpose:     read a string from a text file and determine its     *)
  990.   (*              length.                                              *)
  991.   (* Interface:   IN_FILE -       File to be read                      *)
  992.   (*              IN_STR_LN -     Index in line to be read             *)
  993.   (*              IN_STR_BODY -   Body of the line                     *)
  994.   (* Author/date: Maarten Rooda, September 1990.                       *)
  995.   (* Modified:    Boudewijn Pelt, June 1991 & July 1991.               *)
  996.   (*              Hans Rabouw, March 1992                              *)
  997.   (*********************************************************************)
  998.   PROCEDURE READ_STRING;
  999.   VAR
  1000.       INDEX: INTEGER;
  1001.  
  1002.   BEGIN
  1003.       (* File is already open and in inspection mode.                  *)
  1004.       (* A prompt, if needed, has already been issued.                 *)
  1005.       IN_STR_LN := 0;
  1006.       INDEX := 1;
  1007.       IF NOT (EOF(IN_FILE)) OR (EOLN (IN_FILE))  THEN
  1008.       BEGIN
  1009.           WHILE NOT (EOLN (IN_FILE) OR (INDEX > NR_CHARS_TO_READ)) DO
  1010.           BEGIN
  1011.               READ(IN_FILE, IN_STR_BODY[INDEX]);
  1012.               INDEX := INDEX + 1;
  1013.           END (*WHILE*);
  1014.           IN_STR_LN := INDEX - 1;
  1015.           IF IN_STR_LN > 0 THEN
  1016.               WHILE (IN_STR_BODY[IN_STR_LN] = ' ') AND
  1017.                     (IN_STR_LN > 1) DO
  1018.                    IN_STR_LN := IN_STR_LN - 1;
  1019.  
  1020.           (* If not all of the string has been filled, write spaces to *)
  1021.           (* the cells that have not been filled.                      *)
  1022.  
  1023.           FOR INDEX := INDEX TO STRING_FIXED_L DO
  1024.               IN_STR_BODY[INDEX] := ' ';
  1025.       END (*IF*);
  1026.   END (*READ_STRING*);
  1027.  
  1028.   (*********************************************************************)
  1029.   (* Routine:     UC - convert character to Upper-Case                 *)
  1030.   (* Purpose:     To transform lower case letters to their uppercase   *)
  1031.   (*              equivalent.                                          *)
  1032.   (* Interface:   INCHAR -    Character to be converted.               *)
  1033.   (*              <RETURNS> - Converted character.                     *)
  1034.   (* Author/Date: Vamp project management, october 1983.               *)
  1035.   (*********************************************************************)
  1036.   FUNCTION  UC;
  1037.   BEGIN
  1038.       IF (INCHAR >= 'a') AND (INCHAR <= 'z') THEN
  1039.           UC := CHR (ORD(INCHAR) - ORD('a') + ORD('A'))
  1040.       ELSE
  1041.           UC := INCHAR;
  1042.   END (*UC*);
  1043.  
  1044.   (*********************************************************************)
  1045.   (* Routine:     VAL_INI_DATA                                         *)
  1046.   (* Purpose:     Check if the run_info structure VAL_INFO is valid    *)
  1047.   (*              if this is not the case then attempt to fix it       *)
  1048.   (*              or return an error. (Make OK FALSE)                  *)
  1049.   (* Interface:   VAL_INFO -  Data from initialization.                *)
  1050.   (*              OK -        TRUE if data OK.                         *)
  1051.   (* Author/date: Boudewijn Pelt, June 1991.                           *)
  1052.   (*********************************************************************)
  1053.   PROCEDURE VAL_INI_DATA;
  1054.   CONST
  1055.       AUX_STR_L = MAX_MODE_L;
  1056.  
  1057.   VAR
  1058.       ERROR:      BOOLEAN;
  1059.       AUX_STRING: PACKED ARRAY [1..AUX_STR_L] OF CHAR;
  1060.       I:          INTEGER;
  1061.  
  1062.   BEGIN
  1063.       ERROR :=  FALSE;
  1064.       WITH VAL_INFO DO
  1065.       BEGIN
  1066.           IF NOT (CHECK_SYNTAX(CLIP_LPAR, CLIP_RPAR, CLIP_END,
  1067.                                 CLIP_CC, OPTION_MARKER)) THEN
  1068.               ERROR := TRUE;
  1069.  
  1070.           (* Check MODE and set ERROR.                                *)
  1071.           IF MODE[1] IN ['I', 'i'] THEN
  1072.               AUX_STRING :='INTERACTIVE_MODE'
  1073.           ELSE IF MODE[1] IN ['A', 'a'] THEN
  1074.               AUX_STRING :='AUTO_MODE       '
  1075.           ELSE IF MODE[1] IN ['H', 'h'] THEN
  1076.               AUX_STRING :='HELPFUL_MODE    '
  1077.           ELSE IF MODE[1] IN ['D', 'd'] THEN
  1078.               AUX_STRING :='DEBUG_MODE      '
  1079.           ELSE
  1080.               ERROR := TRUE;
  1081.         
  1082.           IF NOT ERROR THEN
  1083.               FOR I := 1 TO MAX_MODE_L DO
  1084.                   MODE[I] := AUX_STRING[I];
  1085.         
  1086.           (* Check MESSAGE_DESTINATION and set ERROR.                 *)
  1087.           IF MESSAGE_DESTINATION[1] IN ['F', 'f'] THEN
  1088.               AUX_STRING := 'FILE            '
  1089.           ELSE IF MESSAGE_DESTINATION[1] IN ['T', 't'] THEN
  1090.               AUX_STRING := 'TERMINAL        '
  1091.           ELSE IF MESSAGE_DESTINATION[1] IN ['B', 'b'] THEN
  1092.               AUX_STRING := 'BOTH            '
  1093.           ELSE IF MESSAGE_DESTINATION[1] IN ['N', 'n'] THEN
  1094.               AUX_STRING := 'NONE            '
  1095.           ELSE
  1096.               ERROR := TRUE;
  1097.         
  1098.           IF NOT ERROR THEN
  1099.               FOR I := 1 TO MAX_M_D_L DO
  1100.                   MESSAGE_DESTINATION[I] := AUX_STRING[I];
  1101.         
  1102.           (* Check EXTR_MODE and set ERROR.                           *)
  1103.           IF EXTR_MODE[1] IN ['E', 'e'] THEN
  1104.               AUX_STRING := 'EXTRACTED       '
  1105.           ELSE IF EXTR_MODE[1] IN ['O', 'o'] THEN
  1106.               AUX_STRING := 'OMITTED         '
  1107.           ELSE
  1108.               ERROR := TRUE;
  1109.         
  1110.           IF NOT ERROR THEN
  1111.               FOR I := 1 TO MAX_EXTR_MODE_L DO
  1112.                   EXTR_MODE[I] := AUX_STRING[I];
  1113.         
  1114.       END (*WITH*);
  1115.       OK := NOT ERROR;
  1116.   END (*VAL_INI_DATA*);
  1117.  
  1118.   (*-----------   File Table routines (ADT)  --------------------------*)
  1119.  
  1120.   (*********************************************************************)
  1121.   (* Routine:     FT_ABS_LINE_NUMBER - File Table ABSolute LINE NUMBER.*)
  1122.   (* Purpose:     To return the absolute line number of a source line  *)
  1123.   (*              the source file.                                     *)
  1124.   (* Interface:   SOURCE_LINE -   The specified source line.           *)
  1125.   (*              RETURNS -       Absolute line number of the given    *)
  1126.   (*                              SOURCE_LINE.                         *)
  1127.   (*********************************************************************)
  1128.   FUNCTION FT_ABS_LINE_NUMBER;
  1129.   BEGIN
  1130.       FT_ABS_LINE_NUMBER := SOURCE_LINE.ID;
  1131.   END (*FUNCTION FT_ABS_LINE_NUMBER*);
  1132.  
  1133.   (*********************************************************************)
  1134.   (* Routine:     FT_CHECK_FILE                                        *)
  1135.   (* Purpose:     Checks whether a file is acccessable or not.         *)
  1136.   (* Interface:   FILE_SPEC - Specification of file to check.          *)
  1137.   (*              RETURNS -   Code of a possible error.                *)
  1138.   (* FT vars:     CURR_IN_FILE.                                        *)
  1139.   (*********************************************************************)
  1140.   FUNCTION FT_CHECK_FILE;
  1141.   VAR
  1142.       ERROR_CODE:         ERROR_CODE_;
  1143.       DUMMY_FILE_OK:      BOOLEAN;
  1144.       DUMMY_ERROR_MSG:    ERROR_MSG_;
  1145.  
  1146.   BEGIN
  1147.       EXT_FILE_PREP (CURR_IN_FILE, FILE_SPEC, INSP_MODE, DUMMY_FILE_OK,
  1148.                      ERROR_CODE, DUMMY_ERROR_MSG);
  1149.       IF ERROR_CODE<=0 THEN
  1150.           CLOSE (CURR_IN_FILE);
  1151.       FT_CHECK_FILE := ERROR_CODE;
  1152.   END (*FT_CHECK_FILE*);
  1153.  
  1154.   (*********************************************************************)
  1155.   (* Routine:     FT_EOF                                               *)
  1156.   (* Purpose:     The function examines if the currently read file is  *)
  1157.   (*              exhausted.                                           *)
  1158.   (* Interface:   RETURNS - TRUE if the file is exhausted.             *)
  1159.   (* FT vars:     CURR_IN_FILE.                                        *)
  1160.   (*********************************************************************)
  1161.   FUNCTION FT_EOF;
  1162.   BEGIN
  1163.       IF NOT EOF(CURR_IN_FILE) THEN
  1164.           FT_EOF := FALSE
  1165.       ELSE
  1166.           FT_EOF := TRUE;
  1167.   END (*FT_EOF*);
  1168.  
  1169.   (*********************************************************************)
  1170.   (* Routine:     FT_GET_CHAR                                          *)
  1171.   (* Purpose:     To locate a character at a given position in a       *)
  1172.   (*              source_line and to return this character.            *)
  1173.   (* Interface:   SOURCE_LINE -    The source line.                    *)
  1174.   (*              INDEX -          Index of the desired character.     *)
  1175.   (*              RETURNS -        The desired character.              *)
  1176.   (* CLIP objs:   MAX_LINE.                                            *)
  1177.   (*********************************************************************)
  1178.   FUNCTION FT_GET_CHAR;
  1179.   BEGIN
  1180.       IF (INDEX > MAX_LINE) OR (INDEX <= 0) THEN
  1181.       BEGIN
  1182.           WRITELN (OUTPUT, 'FT-GET-CHAR (a): ',
  1183.                            'System Failure... Call maintenance.');
  1184.           CLIP_STOP;
  1185.       END (*IF*);
  1186.       IF INDEX > SOURCE_LINE.USED THEN
  1187.       BEGIN
  1188.           WRITELN (OUTPUT, 'FT-GET-CHAR (B): ',
  1189.                            'System Failure... Call maintenance.');
  1190.           CLIP_STOP;
  1191.       END (*IF*);
  1192.  
  1193.       (* Index is within legal range. Proceed...                       *)
  1194.       FT_GET_CHAR := SOURCE_LINE.CHARS[INDEX];
  1195.   END (*FT_GET_CHAR*);
  1196.  
  1197.   (*********************************************************************)
  1198.   (* Routine:     FT_GET_FILE_SPEC                                     *)
  1199.   (* Purpose:     To return the file specification of a source line    *)
  1200.   (* Interface:   SOURCE_LINE -     The source line.                   *)
  1201.   (*              FILE_SPEC -       The wanted file specification.     *)
  1202.   (* FT vars:     FILE_TABLE.                                          *)
  1203.   (*********************************************************************)
  1204.   PROCEDURE FT_GET_FILE_SPEC;
  1205.   VAR
  1206.       INDEX: FT_INDEX_;
  1207.  
  1208.   BEGIN
  1209.       (* Beware of non-existing line identifications.                  *)
  1210.       IF (SOURCE_LINE.ID <= 0) OR
  1211.          (SOURCE_LINE.ID > FILE_TABLE[LAST_FILE].LAST) THEN
  1212.       BEGIN
  1213.           WRITELN (OUTPUT, 'FT-GET-FILE-SPEC: ',
  1214.                            'System Failure... Call maintenance.');
  1215.           CLIP_STOP;
  1216.       END (*IF*);
  1217.  
  1218.       (* Line surely exist in FT. Find its specification.              *)
  1219.       INDEX := 1;
  1220.       WHILE FILE_TABLE[INDEX].LAST < SOURCE_LINE.ID DO
  1221.           INDEX := INDEX+1;
  1222.       FILE_SPEC := FILE_TABLE[INDEX].FILE_SPEC;
  1223.   END (*FT_GET_FILE_SPEC*);
  1224.  
  1225.   (*********************************************************************)
  1226.   (* Routine:     FT_GET_INDENT                                        *)
  1227.   (* Purpose:     To return the indentation of a line                  *)
  1228.   (* Interface:   SOURCE_LINE -   The source line.                     *)
  1229.   (*              RETURNS -       The indentation of SOURCE_LINE.      *)
  1230.   (*********************************************************************)
  1231.   FUNCTION FT_GET_INDENT;
  1232.   BEGIN
  1233.       FT_GET_INDENT := SOURCE_LINE.INDENT;
  1234.   END (*FT_GET_INDENT*);
  1235.  
  1236.   (*********************************************************************)
  1237.   (* Routine:     FT_GET_LINE_LENGTH                                   *)
  1238.   (* Purpose:     To return the length of a line                       *)
  1239.   (* Interface:   SOURCE_LINE -   Line-descriptor to be examined.      *)
  1240.   (*              RETURNS -       Length of given line.                *)
  1241.   (*********************************************************************)
  1242.   FUNCTION FT_GET_LINE_LENGTH;
  1243.   BEGIN
  1244.       FT_GET_LINE_LENGTH := SOURCE_LINE.USED;
  1245.   END (*FT_GET_LINE_LENGTH*);
  1246.  
  1247.   (*********************************************************************)
  1248.   (* Routine:     FT_GET_LINE_NUMBER                                   *)
  1249.   (* Purpose:     To return the line number of a source line.          *)
  1250.   (* Interface:   SOURCE_LINE -   The source line                      *)
  1251.   (*              RETURNS -       Line number or error code.           *)
  1252.   (* FT vars:     FILE_TABLE.                                          *)
  1253.   (*********************************************************************)
  1254.   FUNCTION FT_GET_LINE_NUMBER;
  1255.   VAR
  1256.       INDEX:   FT_INDEX_;
  1257.  
  1258.   BEGIN
  1259.       (* Beware of non-existing line identifications.                  *)
  1260.       IF (SOURCE_LINE.ID <= 0) OR
  1261.           (SOURCE_LINE.ID > FILE_TABLE[LAST_FILE].LAST) THEN
  1262.       BEGIN
  1263.           WRITELN (OUTPUT, 'FT_GET_LINE_NUMBER: ',
  1264.                            'System Failure... Call maintenance.');
  1265.           CLIP_STOP;
  1266.       END (*IF*);
  1267.  
  1268.       (* Line surely exist in FT. Find its number.                     *)
  1269.       INDEX := 1;
  1270.       WHILE FILE_TABLE[INDEX].LAST < SOURCE_LINE.ID DO
  1271.           INDEX := INDEX + 1;
  1272.       FT_GET_LINE_NUMBER := SOURCE_LINE.ID - FILE_TABLE[INDEX].FIRST + 1;
  1273.   END (*FT_GET_LINE_NUMBER*);
  1274.  
  1275.   (*********************************************************************)
  1276.   (* Routine:     FT_GET_POS_OPTION_MARKER                             *)
  1277.   (* Purpose:     Return the value of POS_OPTION_MARKER.               *)
  1278.   (* Interface:   SOURCE_LINE -   Line-descriptor to be examined.      *)
  1279.   (*              RETURNS -       Position of the OPTION_MARKER.       *)
  1280.   (*********************************************************************)
  1281.   FUNCTION FT_GET_POS_OPTION_MARKER;
  1282.   BEGIN
  1283.       FT_GET_POS_OPTION_MARKER := SOURCE_LINE.POS_OPTION_MARKER;
  1284.   END (*FT_GET_POS_MARKER*);
  1285.  
  1286.   (*********************************************************************)
  1287.   (* Routine:     FT_INCLOSE                                           *)
  1288.   (* Purpose:     Close the current input file.                        *)
  1289.   (* Interface:   RETURNS -   Code of a possible error.                *)
  1290.   (* FT vars:     CURR_IN_FILE.                                        *)
  1291.   (*********************************************************************)
  1292.   FUNCTION FT_INCLOSE;
  1293.   VAR
  1294.       ERROR_CODE: ERROR_CODE_;
  1295.  
  1296.   BEGIN
  1297.       EXT_FILE_CLOSE (CURR_IN_FILE, ERROR_CODE);
  1298.       FT_INCLOSE := ERROR_CODE;
  1299.   END (*FT_INCLOSE*);
  1300.  
  1301.   (*********************************************************************)
  1302.   (* Routine:     FT_INIT                                              *)
  1303.   (* Purpose:     General initialization of the file table. It is only *)
  1304.   (*              activated once at the start of an run.               *)
  1305.   (* FT vars:     FILE_TABLE, LAST_LINE, LAST_FILE, SPACE.             *)
  1306.   (*********************************************************************)
  1307.   PROCEDURE FT_INIT;
  1308.   VAR
  1309.       K:  FT_INDEX_;
  1310.  
  1311.   BEGIN
  1312.       FOR K := 1 TO FT_SIZE DO
  1313.       WITH FILE_TABLE[K] DO
  1314.       BEGIN
  1315.           FILE_SPEC.LENGTH := 0;
  1316.           FIRST := 0;
  1317.           LAST  := 0;
  1318.       END (*WITH*);
  1319.       LAST_LINE := 0;
  1320.       LAST_FILE := 0;
  1321.       SPACE := [CHR(0)  .. CHR(9),  CHR(14) .. CHR(25),
  1322.                 CHR(28) .. CHR(32), CHR(11),   CHR(127)];
  1323.   END (*FT_INIT*);
  1324.  
  1325.   (*********************************************************************)
  1326.   (* Routine:     FT_INIT_LINE                                         *)
  1327.   (* Purpose:     Initialization of a LINE_DES_-object.                *)
  1328.   (*********************************************************************)
  1329.   PROCEDURE FT_INIT_LINE;
  1330.   BEGIN
  1331.       WITH LINE DO
  1332.       BEGIN
  1333.           INDENT            := 0;
  1334.           USED              := 0;
  1335.           ID                := 0;
  1336.           POS_OPTION_MARKER := 0;
  1337.       END (*WITH*);
  1338.   END (*FT_INIT_LINE*);
  1339.  
  1340.   (*********************************************************************)
  1341.   (* Routine:     FT_INOPEN                                            *)
  1342.   (* Purpose:     Opens a new file with the given specification for    *)
  1343.   (*              read access.                                         *)
  1344.   (* Interface:   FILE_SPEC -    Specification of file to open.        *)
  1345.   (*              RETURNS -      Code of a possible error.             *)
  1346.   (* FT vars:     FILE_TABLE, LAST_FILE, CURR_IN_FILE.                 *)
  1347.   (*********************************************************************)
  1348.   FUNCTION FT_INOPEN;
  1349.   VAR
  1350.       ERROR_CODE:     ERROR_CODE_;
  1351.       DUMMY_FILE_OK:  BOOLEAN;
  1352.       DUMMY_ERROR_MSG: ERROR_MSG_;
  1353.  
  1354.   BEGIN
  1355.       EXT_FILE_PREP (CURR_IN_FILE, FILE_SPEC, INSP_MODE, DUMMY_FILE_OK,
  1356.                      ERROR_CODE, DUMMY_ERROR_MSG);
  1357.       IF ERROR_CODE = 0 THEN
  1358.       BEGIN
  1359.           LAST_FILE := LAST_FILE+1;
  1360.           FILE_TABLE[LAST_FILE].FILE_SPEC := FILE_SPEC;
  1361.       END (*IF*);
  1362.       FT_INOPEN := ERROR_CODE;
  1363.   END (*FT_INOPEN*);
  1364.  
  1365.   (*********************************************************************)
  1366.   (* Routine:     FT_OUTOPEN                                           *)
  1367.   (* Purpose:     Opens a new file with the given specification for    *)
  1368.   (*              write access.                                        *)
  1369.   (* Interface:   FILE_SPEC - Specification of outputfile.             *)
  1370.   (*              RETURNS -   Code of a possible error.                *)
  1371.   (* FT vars:     CURR_OUT_FILE.                                       *)
  1372.   (*********************************************************************)
  1373.   FUNCTION FT_OUTOPEN;
  1374.   VAR
  1375.       ERROR_CODE: ERROR_CODE_;
  1376.       DUMMY_FILE_OK:  BOOLEAN;
  1377.       DUMMY_ERROR_MSG: ERROR_MSG_;
  1378.  
  1379.   BEGIN
  1380.       EXT_FILE_PREP (CURR_OUT_FILE, FILE_SPEC, GEN_MODE, DUMMY_FILE_OK,
  1381.                      ERROR_CODE, DUMMY_ERROR_MSG);
  1382.  
  1383.       (* The opening was successfull. Make ERROR_CODE equal to         *)
  1384.       (* STATUS (CURR_OUT_FILE) in case an error occured during the    *)
  1385.       (* REWRITE operation (flagged by a value <> -1).                 *)
  1386.       FT_OUTOPEN := ERROR_CODE;
  1387.   END (*FT_OUTOPEN*);
  1388.  
  1389.   (*********************************************************************)
  1390.   (* Routine:     FT_OUTCLOSE                                          *)
  1391.   (* Purpose:     Close the current output file.                       *)
  1392.   (* Interface:   RETURNS -   Code of a possible error.                *)
  1393.   (* FT vars:     CURR_OUT_FILE.                                       *)
  1394.   (*********************************************************************)
  1395.   FUNCTION FT_OUTCLOSE;
  1396.   VAR
  1397.       ERROR_CODE: ERROR_CODE_;
  1398.  
  1399.   BEGIN
  1400.       EXT_FILE_CLOSE (CURR_OUT_FILE, ERROR_CODE);
  1401.       FT_OUTCLOSE := ERROR_CODE;
  1402.   END (*FT_OUTCLOSE*);
  1403.  
  1404.   (*********************************************************************)
  1405.   (* Routine:     FT_RDLN                                              *)
  1406.   (* Purpose:     Read the next line from the current source-file.     *)
  1407.   (* Interface:   LINE -  A source-line is returned in the form of a   *)
  1408.   (*                      line descriptor.                             *)
  1409.   (* FT vars:     SPACE                                                *)
  1410.   (*********************************************************************)
  1411.   PROCEDURE FT_RDLN;
  1412.   CONST
  1413.       TAB =   8;
  1414.   VAR
  1415.       STR132: STRING132_;
  1416.       INDEX,
  1417.       K:      INTEGER;
  1418.  
  1419.   BEGIN
  1420.       WITH LINE DO
  1421.       BEGIN
  1422.           INDENT := 0;
  1423.           USED := 0;
  1424.           POS_OPTION_MARKER := 0;
  1425.           WITH STR132 DO
  1426.           BEGIN
  1427.               BODY := EMPTY_STRING_FIXED;
  1428.               LENGTH := 0;
  1429.               WHILE (NOT EOLN(CURR_IN_FILE)) AND
  1430.                     (LENGTH < STRING_FIXED_L)     DO
  1431.               BEGIN
  1432.                   LENGTH := LENGTH + 1;
  1433.                   READ (CURR_IN_FILE, BODY[LENGTH]);
  1434.               END (*WHILE*);
  1435.               READLN (CURR_IN_FILE);
  1436.  
  1437.               (* Check spaces at beginning of string and calculate     *)
  1438.               (* INDENT.                                               *)
  1439.               INDEX := 1;
  1440.               WHILE (INDEX < LENGTH) AND (BODY[INDEX] IN SPACE) DO
  1441.               BEGIN
  1442.                   IF BODY[INDEX] = CHR(9) THEN
  1443.                       INDENT := INDENT + (TAB - (INDENT MOD TAB))
  1444.                   ELSE
  1445.                       INDENT := INDENT + 1;
  1446.                   INDEX := INDEX + 1;
  1447.               END (*WHILE*);
  1448.  
  1449.               LAST_LINE := LAST_LINE + 1;
  1450.               FOR K := INDEX TO LENGTH DO
  1451.                   CHARS[K-INDEX+1] := BODY[K];
  1452.  
  1453.               (* Remove spaces at the end of the line.                 *)
  1454.               IF LENGTH > 0 THEN
  1455.               BEGIN
  1456.                   USED  := LENGTH-INDEX+1;
  1457.   (*********************************************************************)
  1458.   (* Modified 14/10/93 by Mark Kramer to solve an index out of bound   *)
  1459.   (* problem when bound checks are on.                                 *)
  1460.   (*             WHILE  (USED >0) AND (CHARS[USED] IN SPACE) DO        *)
  1461.   (*                  USED := USED-1;                                  *)
  1462.  
  1463.                  WHILE  (USED > 1) AND (CHARS[USED] IN SPACE) DO
  1464.                       USED := USED-1;
  1465.                  IF (USED = 1) AND (CHARS[USED] IN SPACE) THEN
  1466.                       USED := USED-1;
  1467.  
  1468.   (* End of modification 14/10/93.                                     *)
  1469.   (*********************************************************************)
  1470.               END (*IF*);
  1471.               ID := LAST_LINE;
  1472.           END (*WITH*);
  1473.  
  1474.           (* Update the File Table.                                    *)
  1475.           IF FILE_TABLE[LAST_FILE].FIRST = 0 THEN
  1476.               FILE_TABLE[LAST_FILE].FIRST := LAST_LINE;
  1477.           FILE_TABLE[LAST_FILE].LAST := LAST_LINE;
  1478.       END (*WITH*);
  1479.   END (*FT_RDLN*);
  1480.  
  1481.   (*********************************************************************)
  1482.   (* Routine:     FT_WRLN                                              *)
  1483.   (* Purpose:     Write a line to the current output file.             *)
  1484.   (* Interface:   LINE -         The line to be written.               *)
  1485.   (*              NR_BLANKS -    The number of blanks leading the      *)
  1486.   (*                             first character of LINE.              *)
  1487.   (*              DESTINATION -  The destination of the line (screen,  *)
  1488.   (*                             output file, reportfile etc.)         *)
  1489.   (*              REPORT_FILE -  Report file for output.               *)
  1490.   (*********************************************************************)
  1491.   PROCEDURE FT_WRLN;
  1492.   VAR
  1493.       INDEX:              INTEGER;
  1494.       NR_TOTAL_BLANKS:    INTEGER;
  1495.  
  1496.   BEGIN (*FT_WRLN*)
  1497.       NR_TOTAL_BLANKS := LINE.INDENT + NR_BLANKS;
  1498.       CASE DESTINATION OF
  1499.       0:  BEGIN
  1500.               FOR INDEX := 1 TO LINE.USED DO
  1501.                   WRITE (OUTPUT, LINE.CHARS[INDEX]);
  1502.               WRITELN (OUTPUT);
  1503.           END;
  1504.       1:  BEGIN
  1505.               WRLN_STRING (CURR_OUT_FILE, LINE.CHARS, LINE.USED,
  1506.                            NR_TOTAL_BLANKS);
  1507.           END;
  1508.       2:  BEGIN
  1509.               FOR INDEX := 1 TO LINE.USED DO
  1510.                   WRITE (OUTPUT, LINE.CHARS[INDEX]);
  1511.               WRITELN (OUTPUT);
  1512.           END;
  1513.       3:  BEGIN
  1514.               WRLN_STRING (REPORT_FILE, LINE.CHARS, LINE.USED, 0);
  1515.           END;
  1516.       END (*CASE*);
  1517.  
  1518.   END (*FT_WRLN*);
  1519.  
  1520.   (*-----------   Segment Table routines (ADT)  -----------------------*)
  1521.  
  1522.   (*********************************************************************)
  1523.   (* Routine:     ST_RD - Segment Table ReaD.                          *)
  1524.   (* Purpose:     Read a line from the SEGMENT_TABLE.                  *)
  1525.   (* Interface:   LINE  - The line which is read.                      *)
  1526.   (*              INDEX - The position of the line in SEGMENT_TABLE.   *)
  1527.   (* ST vars:     SEGMENT_TABLE.                                       *)
  1528.   (*********************************************************************)
  1529.   PROCEDURE ST_RD (VAR LINE: LINE_DES_; INDEX: ST_INDEX_);
  1530.   BEGIN
  1531.  
  1532.       LINE := SEGMENT_TABLE.LINES[INDEX];
  1533.   END (*ST_READ*);
  1534.  
  1535.   (*********************************************************************)
  1536.   (* Routine:    ST_WR - Segment Table WRite.                          *)
  1537.   (* Purpose:    Write a line to the SEGMENT_TABLE.                    *)
  1538.   (* Interface:  LINE - The line which is written                      *)
  1539.   (*             INDEX- The position of the LINE.                      *)
  1540.   (* ST var:     SEGMENT_TABLE.                                        *)
  1541.   (*********************************************************************)
  1542.   PROCEDURE ST_WR (LINE: LINE_DES_; INDEX: ST_INDEX_);
  1543.   BEGIN
  1544.  
  1545.       SEGMENT_TABLE.LINES[INDEX] := LINE;
  1546.   END (*ST_WR*);
  1547.  
  1548.   (*********************************************************************)
  1549.   (* Routine:     ST_ABS_SEG - Segment Table ABSolute SEGment          *)
  1550.   (* Purpose:     To return the absolute line number of the first      *)
  1551.   (*              line of the segment.                                 *)
  1552.   (* Interface:   SEGMENT - Given segment                              *)
  1553.   (*              Function result - The absolute line number of the    *)
  1554.   (*                                first line of SEGMENT.             *)
  1555.   (* ST vars:     SEGMENT_TABLE.                                       *)
  1556.   (*********************************************************************)
  1557.   FUNCTION ST_ABS_SEG;
  1558.   VAR
  1559.       LINE: LINE_DES_;
  1560.  
  1561.   BEGIN
  1562.       IF SEGMENT.FIRST > 0 THEN
  1563.       BEGIN
  1564.           ST_RD (LINE, SEGMENT.FIRST);
  1565.           ST_ABS_SEG := FT_ABS_LINE_NUMBER (LINE);
  1566.       END (*IF*)
  1567.   END (*ST_ABS_SEG*);
  1568.  
  1569.   (*********************************************************************)
  1570.   (* Routine:     ST_GET_FILE_SPEC                                     *)
  1571.   (* Purpose:     To return the file specification of the source file  *)
  1572.   (*              of the segment.                                      *)
  1573.   (* Interface:   SEGMENT - Given segment.                             *)
  1574.   (*              FILE_SPEC  - The file specification.                 *)
  1575.   (* ST vars:     SEGMENT_TABLE.                                       *)
  1576.   (*********************************************************************)
  1577.   PROCEDURE ST_GET_FILE_SPEC;
  1578.   VAR
  1579.       LINE: LINE_DES_;
  1580.  
  1581.   BEGIN
  1582.       ST_RD (LINE, SEGMENT.FIRST);
  1583.       FT_GET_FILE_SPEC (LINE, FILE_SPEC);
  1584.   END (*ST_GET_FILE_SPEC*);
  1585.  
  1586.   (*********************************************************************)
  1587.   (* Routine:     ST_GET_INDENT                                        *)
  1588.   (* Purpose:     Return the indentation of segment.                   *)
  1589.   (* Interface:   SEG -       Segment to be investigated.              *)
  1590.   (*              RETURNS -   Indent value or error-code.              *)
  1591.   (*********************************************************************)
  1592.   FUNCTION ST_GET_INDENT;
  1593.   VAR
  1594.       LINE: LINE_DES_;
  1595.  
  1596.   BEGIN
  1597.       ST_RD (LINE, SEG.FIRST);
  1598.       ST_GET_INDENT := FT_GET_INDENT (LINE);
  1599.   END (*ST_GET_INDENT*);
  1600.  
  1601.   (*********************************************************************)
  1602.   (* Routine:     ST_GET_LINE                                          *)
  1603.   (* Purpose:     Retrieves next line from the currently read segment. *)
  1604.   (* Interface:   LINE -  Returned line.                               *)
  1605.   (* ST vars:     SEGMENT_TABLE, LAST_READ_SEG.                        *)
  1606.   (*********************************************************************)
  1607.   PROCEDURE ST_GET_LINE;
  1608.   VAR
  1609.       INDEX: ST_INDEX_;
  1610.  
  1611.   BEGIN
  1612.       WITH LAST_READ_SEG DO
  1613.       BEGIN
  1614.           IF ST_IS_EMPTY_SEG (LAST_SEG) THEN
  1615.           BEGIN
  1616.               (* ST_GET_LINE has not properly been prepared for reading.*)
  1617.               WRITELN (OUTPUT, 'ST-GET-LN: ',
  1618.                                'System Failure... Call maintenance.');
  1619.               CLIP_STOP;
  1620.           END
  1621.           ELSE
  1622.           BEGIN
  1623.               INDEX := LAST_LINE + 1;
  1624.               IF INDEX > LAST_SEG.LAST THEN
  1625.               BEGIN
  1626.                   (* Segment exhausted. Return LINE with ID value 0.   *)
  1627.                   LINE.ID := 0;
  1628.               END
  1629.               ELSE
  1630.               BEGIN
  1631.                   (* Retrieve line at position INDEX from the ST and   *)
  1632.                   (* update LAST_READ_SEG.                             *)
  1633.                   ST_RD (LINE, INDEX);
  1634.                   LAST_LINE := INDEX;
  1635.               END (*IF*);
  1636.          END (*IF*);
  1637.      END (*WITH*);
  1638.   END (*ST_GET_LINE*);
  1639.  
  1640.   (*********************************************************************)
  1641.   (* Routine:     ST_GET_OPTION_LINE                                   *)
  1642.   (* Purpose:     To retrieve the first line from a segment which      *)
  1643.   (*              holds an option marker.                              *)
  1644.   (* Interface:   SEG -     The segment                                *)
  1645.   (*              LINE -    The first line holding an option marker    *)
  1646.   (* ST vars:     SEGMENT_TABLE, LAST_READ_SEG.                        *)
  1647.   (*********************************************************************)
  1648.   PROCEDURE ST_GET_OPTION_LINE;
  1649.   VAR
  1650.       INDEX:     ST_INDEX_;
  1651.       POSITION:  INTEGER;
  1652.       AUX_LINE:  LINE_DES_;
  1653.  
  1654.   BEGIN
  1655.       INDEX := SEG.FIRST;
  1656.       POSITION := 0;
  1657.       IF INDEX > 0 THEN
  1658.       BEGIN
  1659.           WHILE (POSITION =0) AND (INDEX <= SEG.LAST) DO
  1660.           BEGIN
  1661.               ST_RD (AUX_LINE, INDEX);
  1662.               POSITION := FT_GET_POS_OPTION_MARKER (AUX_LINE);
  1663.               IF POSITION =0 THEN
  1664.                  INDEX := INDEX + 1;
  1665.           END (*WHILE*);
  1666.           IF POSITION =0 THEN
  1667.               LINE.ID := 0
  1668.           ELSE
  1669.               LINE := AUX_LINE;
  1670.           WITH LAST_READ_SEG DO
  1671.           BEGIN
  1672.               LAST_SEG  := SEG;
  1673.               LAST_LINE := INDEX;
  1674.           END (*WITH*);
  1675.       END
  1676.       ELSE
  1677.       BEGIN
  1678.           LAST_READ_SEG.LAST_SEG.FIRST := 0;
  1679.           LAST_READ_SEG.LAST_SEG.LAST  := 0;
  1680.           LAST_READ_SEG.LAST_LINE      := 0;
  1681.           LINE.ID := 0;
  1682.       END (*IF*);
  1683.   END (*ST_GET_OPTION_LINE*);
  1684.  
  1685.   (*********************************************************************)
  1686.   (* Routine:     ST_GET_SEG                                           *)
  1687.   (* Purpose:     Retrieve the first line of a given segment from ST.  *)
  1688.   (* Interface:   LINE -  Returned line.                               *)
  1689.   (*              SEG -   Segment to read from.                        *)
  1690.   (* ST vars:     SEGMENT_TABLE, LAST_READ_SEG.                        *)
  1691.   (*********************************************************************)
  1692.   PROCEDURE ST_GET_SEG;
  1693.   BEGIN
  1694.       IF ST_IS_EMPTY_SEG (SEG) THEN
  1695.       BEGIN
  1696.           (* Return virtual line and reset LAST_READ_SEG.              *)
  1697.           LINE.ID := 0;
  1698.           ST_INIT_SEG (LAST_READ_SEG.LAST_SEG);
  1699.           LAST_READ_SEG.LAST_LINE := 0;
  1700.       END
  1701.       ELSE
  1702.       BEGIN
  1703.           ST_RD (LINE, SEG.FIRST);
  1704.           WITH LAST_READ_SEG DO
  1705.           BEGIN
  1706.               LAST_SEG  := SEG;
  1707.               LAST_LINE := SEG.FIRST;
  1708.           END (*WITH*);
  1709.       END (*IF*);
  1710.   END (*ST_GET_SEG*);
  1711.  
  1712.   (*********************************************************************)
  1713.   (* Routine:     ST_GET_SEG_RANGE - Segment Table SEGMENT RANGE       *)
  1714.   (* Purpose:     To return the first and last relative line number of *)
  1715.   (*              a segment.                                           *)
  1716.   (* Interface:   SEGMENT - Given segment.                             *)
  1717.   (*              FIRST   - The line number of the first segment line. *)
  1718.   (*              LAST    - The line number of the last segment line.  *)
  1719.   (* ST vars:     SEGMENT_TABLE.                                       *)
  1720.   (*********************************************************************)
  1721.   PROCEDURE ST_GET_SEG_RANGE;
  1722.   VAR
  1723.       LINE: LINE_DES_;
  1724.  
  1725.   BEGIN
  1726.       FIRST := 0;
  1727.       LAST  := 0;
  1728.       IF SEGMENT.FIRST > 0 THEN
  1729.       BEGIN
  1730.           ST_RD (LINE, SEGMENT.FIRST);
  1731.           FIRST := FT_GET_LINE_NUMBER (LINE);
  1732.           ST_RD (LINE, SEGMENT.LAST);
  1733.           LAST  := FT_GET_LINE_NUMBER (LINE);
  1734.       END (*IF*);
  1735.   END (*ST_GET_SEG_RANGE*);
  1736.  
  1737.   (*********************************************************************)
  1738.   (* Routine:     ST_INIT                                              *)
  1739.   (* Purpose:     General initialization of the segment table. To be   *)
  1740.   (*              invoked only once at the beginning of a run.         *)
  1741.   (* ST vars:     SEGMENT_TABLE, LAST_READ_SEG.                        *)
  1742.   (*********************************************************************)
  1743.   PROCEDURE ST_INIT;
  1744.   BEGIN
  1745.  
  1746.       SEGMENT_TABLE.USED := 0;
  1747.       ST_INIT_SEG (LAST_READ_SEG.LAST_SEG);
  1748.       LAST_READ_SEG.LAST_LINE :=  0;
  1749.   END (*ST_INIT*);
  1750.  
  1751.   (*********************************************************************)
  1752.   (* Routine:     ST_INIT_SEG                                          *)
  1753.   (* Purpose:     To establish a new and empty segment.                *)
  1754.   (* Interface:   SEG -     the segment to initialize.                 *)
  1755.   (*********************************************************************)
  1756.   PROCEDURE ST_INIT_SEG;
  1757.   BEGIN
  1758.       SEG.FIRST :=  0;
  1759.       SEG.LAST  := -1;
  1760.   END (*ST_INIT_SEG*);
  1761.  
  1762.   (*********************************************************************)
  1763.   (* Routine:     ST_IS_EMPTY_SEG                                      *)
  1764.   (* Purpose:     To examine if a segment is empty or not.             *)
  1765.   (* Interface:   SEG -    Segment to be examined.                     *)
  1766.   (*********************************************************************)
  1767.   FUNCTION ST_IS_EMPTY_SEG;
  1768.   BEGIN
  1769.       ST_IS_EMPTY_SEG := (ST_NUMBER_OF_LINES (SEG) <= 0);
  1770.   END (*ST_IS_EMPTY_SEG*);
  1771.  
  1772.   (*********************************************************************)
  1773.   (* Routine:     ST_NUMBER_OF_LINES                                   *)
  1774.   (* Purpose:     To calculate the number of lines in a segment.       *)
  1775.   (* Interface:   SEG - Segment to be investigated.                    *)
  1776.   (*              RETURNS -   Number of lines contained by segment.    *)
  1777.   (*********************************************************************)
  1778.   FUNCTION ST_NUMBER_OF_LINES;
  1779.   BEGIN
  1780.       WITH SEG DO
  1781.       BEGIN
  1782.           IF (FIRST >= 0)  AND  (LAST >= FIRST -1) THEN
  1783.           BEGIN
  1784.               ST_NUMBER_OF_LINES := LAST - FIRST + 1;
  1785.           END
  1786.           ELSE
  1787.           BEGIN
  1788.               WRITELN (OUTPUT, 'ST-NUMBER-OF-LINES: ',
  1789.                                'System Failure... Call maintenance.');
  1790.               CLIP_STOP;
  1791.           END (*IF*);
  1792.       END (*WITH*);
  1793.   END (*ST_NUMBER_OF_LINES*);
  1794.  
  1795.   (*********************************************************************)
  1796.   (* Routine:     ST_PUT_LINE                                          *)
  1797.   (* Purpose:     Add a source line to the last segment in the table.  *)
  1798.   (* Interface:   LINE -  Source line to write.                        *)
  1799.   (*              SEG -   Segment to write to.                         *)
  1800.   (* ST vars:     SEGMENT_TABLE.                                       *)
  1801.   (*********************************************************************)
  1802.   PROCEDURE ST_PUT_LINE;
  1803.   BEGIN
  1804.       IF SEGMENT_TABLE.USED < ST_SIZE THEN
  1805.       BEGIN
  1806.           WITH SEGMENT_TABLE DO
  1807.           BEGIN
  1808.               (* Abort if the ST has become internally inconsistent.   *)
  1809.               (* Othewise add line to the table.                       *)
  1810.               IF SEG.LAST <> USED THEN
  1811.               BEGIN
  1812.                   WRITELN (OUTPUT, 'ST-PUT-LN: ',
  1813.                            'System Failure... Call maintenance.');
  1814.                   CLIP_STOP;
  1815.               END
  1816.               ELSE
  1817.               BEGIN
  1818.                   USED := USED + 1;
  1819.                   ST_WR (LINE, USED);
  1820.                   SEG.LAST := USED;
  1821.               END (*IF*)
  1822.           END (*WITH*);
  1823.       END
  1824.       ELSE
  1825.       BEGIN
  1826.           (* Segment Table to small for this application.              *)
  1827.           WRITELN (OUTPUT, 'ST-PUT-LN: ',
  1828.                            'Parameter Failure... Call maintenance.');
  1829.           CLIP_STOP;
  1830.       END (*IF*);
  1831.   END (*ST_PUT_LINE*);
  1832.  
  1833.   (*********************************************************************)
  1834.   (* Routine:     ST_PUT_SEG                                           *)
  1835.   (* Purpose:     Start a new segment in ST by writing its first line. *)
  1836.   (* Interface:   LINE -  The line to be written.                      *)
  1837.   (*              SEG -   The returned segment.                        *)
  1838.   (* ST vars:     SEGMENT_TABLE, LAST_READ_SEG.                        *)
  1839.   (*********************************************************************)
  1840.   PROCEDURE ST_PUT_SEG;
  1841.   BEGIN
  1842.       IF SEGMENT_TABLE.USED < ST_SIZE THEN
  1843.       BEGIN
  1844.           WITH SEGMENT_TABLE DO
  1845.           BEGIN
  1846.               USED := USED + 1;
  1847.               ST_WR (LINE, USED);
  1848.               SEG.FIRST := USED;
  1849.               SEG.LAST := USED;
  1850.           END (*WITH*);
  1851.       END
  1852.       ELSE
  1853.       BEGIN
  1854.           WRITELN (OUTPUT, 'ST-PUT-SEG: ',
  1855.                            'Parameter Failure... Call maintenance.');
  1856.           CLIP_STOP;
  1857.       END (*IF*);
  1858.   END (*ST_PUT_SEG*);
  1859.  
  1860.   (*********************************************************************)
  1861.   (* Routine:   ST_FINIT - FINIsh Segment Table                        *)
  1862.   (* Purpose:   Remove the segment-file from the directory.            *)
  1863.   (* Interface: -                                                      *)
  1864.   (* ST vars:   SEGMENT_TABLE.                                         *)
  1865.   (*********************************************************************)
  1866.   PROCEDURE ST_FINIT;
  1867.   BEGIN
  1868.   END (*ST_REMOVE*);
  1869.  
  1870.   (*********************************************************************)
  1871.   (* Routine:     ST_SEG_WIDTH -   Segment Table SEGment USED.          *)
  1872.   (* Purpose:     Return the horizontal length of a segment.           *)
  1873.   (* Interface:   SEGMENT  -  Given segment.                           *)
  1874.   (*              RETURNS -   Length of the given segment.             *)
  1875.   (* ST vars:     SEGMENT_TABLE.                                       *)
  1876.   (*********************************************************************)
  1877.   FUNCTION ST_SEG_WIDTH;
  1878.   VAR
  1879.       LINE: LINE_DES_;
  1880.  
  1881.   BEGIN
  1882.       ST_RD (LINE, SEG.FIRST);
  1883.       ST_SEG_WIDTH := FT_GET_LINE_LENGTH (LINE);
  1884.   END;
  1885.  
  1886.   (*********************************************************************)
  1887.   (* Routine:     ST_WRITE_SEG                                         *)
  1888.   (* Purpose:     To write a segment to an output file.                *)
  1889.   (* Interface:   SEG -       Segment to be written.                   *)
  1890.   (*              BLANKS -    Leading blanks for every line of the     *)
  1891.   (*                          segment.                                 *)
  1892.   (*              DESTINATION -   Indicates the destination of the     *)
  1893.   (*                              writing action.                      *)
  1894.   (*              REPORT_FILE -   Report file for output.              *)
  1895.   (*********************************************************************)
  1896.   PROCEDURE ST_WRITE_SEG;
  1897.   VAR
  1898.       K: ST_INDEX_;
  1899.       LINE: LINE_DES_;
  1900.  
  1901.   BEGIN
  1902.       IF SEG.FIRST >0 THEN
  1903.       FOR K := SEG.FIRST TO SEG.LAST DO
  1904.       BEGIN
  1905.           ST_RD (LINE, K);
  1906.           FT_WRLN (LINE, BLANKS, DESTINATION);
  1907.       END (*FOR*);
  1908.   END (*ST_WRITE_SEG*);
  1909.  
  1910.   (*-----------   String Pool routines (ADT)  -------------------------*)
  1911.  
  1912.   (*********************************************************************)
  1913.   (* Routine:     SP_ADD_CHAR                                          *)
  1914.   (* Purpose:     Add character to currently written string.           *)
  1915.   (* Interface:   CH  - Character to be added.                         *)
  1916.   (*              STR - String to add character to.                    *)
  1917.   (*********************************************************************)
  1918.   PROCEDURE SP_ADD_CHAR;
  1919.   BEGIN
  1920.       WITH STRING_POOL^ DO
  1921.       IF USED < SP_SIZE THEN
  1922.       BEGIN
  1923.           (* SP has enough space left to accept another character.     *)
  1924.           USED := USED + 1;
  1925.           CHARS[USED] := CH;
  1926.           IF STR.FIRST =0 THEN
  1927.           BEGIN
  1928.               (* First character of a new string.                      *)
  1929.               STR.FIRST := USED;
  1930.               STR.LAST  := USED;
  1931.           END
  1932.           ELSE
  1933.           BEGIN
  1934.               (* The string already exists. Abort if this string is    *)
  1935.               (* not physically the last one of the SP.                *)
  1936.               IF STR.LAST <>  USED - 1 THEN
  1937.               BEGIN
  1938.                   WRITELN (OUTPUT, 'SP-ADD-CHAR: ',
  1939.                                    'System Failure... Call maintenance.');
  1940.                   CLIP_STOP;
  1941.               END (*IF*);
  1942.               STR.LAST := USED;
  1943.           END (*IF*);
  1944.       END
  1945.       ELSE
  1946.       BEGIN
  1947.           WRITELN (OUTPUT, 'SP-ADD-CHAR: ',
  1948.                            'Parameter Failure... Call maintenance.');
  1949.           CLIP_STOP;
  1950.       END (*IF.WITH*);
  1951.   END (*SP_ADD_CHAR*);
  1952.  
  1953.   (*********************************************************************)
  1954.   (* Routine:     SP_CONC_STR                                          *)
  1955.   (* Purpose:     Concatenation of neighbouring strings.               *)
  1956.   (* Interface:   MASTER -    Recieving string.                        *)
  1957.   (*              SLAVE -     Concatented string                       *)
  1958.   (*********************************************************************)
  1959.   PROCEDURE SP_CONC_STR;
  1960.   BEGIN
  1961.       IF MASTER.FIRST =0 THEN
  1962.           (* An empty MASTER becomes a SLAVE...                        *)
  1963.           MASTER := SLAVE
  1964.       ELSE IF SLAVE.FIRST =0 THEN
  1965.           (* but an empty SLAVE does not bother its MASTER.            *)
  1966.           (* DO NOTHING...                                             *)
  1967.       ELSE IF MASTER.FIRST <>0 THEN
  1968.       BEGIN
  1969.           (* Concatenate only if SLAVE follows MASTER immediately.     *)
  1970.           IF MASTER.LAST + 1 = SLAVE.FIRST THEN
  1971.               MASTER.LAST := SLAVE.LAST
  1972.           ELSE
  1973.           BEGIN
  1974.               WRITELN (OUTPUT, 'SP-CONC-STR: ',
  1975.                                'System Failure... Call maintenance.');
  1976.               CLIP_STOP;
  1977.           END (*IF*);
  1978.       END (*IF*);
  1979.   END (*SP_CONC_STR*);
  1980.  
  1981.   (*********************************************************************)
  1982.   (* Routine:     SP_EQ                                                *)
  1983.   (* Purpose:     To decide if two strings are equal.                  *)
  1984.   (* Interface:   STR1:    First operand.                              *)
  1985.   (*              STR2:    Second operand.                             *)
  1986.   (*              RETURNS: TRUE if both operands are equal.            *)
  1987.   (* SP vars:     STRING_POOL.                                         *)
  1988.   (*********************************************************************)
  1989.   FUNCTION SP_EQ;
  1990.   VAR
  1991.       CONTINUE:   BOOLEAN;
  1992.       INDEX:      INTEGER;
  1993.       STR_L:      INTEGER;
  1994.  
  1995.   BEGIN
  1996.       STR_L := SP_LENGTH_STR (STR1);
  1997.       IF STR_L <> SP_LENGTH_STR (STR2) THEN
  1998.           SP_EQ := FALSE
  1999.       ELSE
  2000.       BEGIN
  2001.           INDEX    := 1;
  2002.           CONTINUE := TRUE;
  2003.           SP_EQ    := TRUE;
  2004.           WHILE (CONTINUE) AND (INDEX <= STR_L) DO
  2005.           BEGIN
  2006.               IF SP_GET_CHAR (INDEX, STR1)
  2007.                                  <> SP_GET_CHAR (INDEX, STR2) THEN
  2008.               BEGIN
  2009.                   CONTINUE := FALSE;
  2010.                   SP_EQ    := FALSE;
  2011.               END (*IF*);
  2012.               INDEX := INDEX + 1;
  2013.           END (*WHILE*);
  2014.       END (*IF*);
  2015.   END (*SP_EQ*);
  2016.  
  2017.   (*********************************************************************)
  2018.   (* Routine:     SP_EXTR_STR                                          *)
  2019.   (* Purpose:     To extract a sequence of characters out of the  SP   *)
  2020.   (*              and to store these characters in a packed array.     *)
  2021.   (* Interface:   STR     - Descriptor of the wanted string.           *)
  2022.   (*              STR132  - The extracted characters.                  *)
  2023.   (*********************************************************************)
  2024.   PROCEDURE SP_EXTR_STR;
  2025.   VAR
  2026.       I:         INTEGER;
  2027.       K:         SP_INDEX_;
  2028.  
  2029.   BEGIN
  2030.       IF STR.FIRST= 0 THEN
  2031.       BEGIN
  2032.           STR132.LENGTH := 0;
  2033.           STR132.BODY   := EMPTY_STRING_FIXED;
  2034.       END
  2035.       ELSE IF STR.LAST <= STRING_POOL^.USED THEN
  2036.       BEGIN
  2037.           STR132.BODY   := EMPTY_STRING_FIXED;
  2038.           I := 0;
  2039.           FOR K := STR.FIRST TO STR.LAST DO
  2040.           BEGIN
  2041.               I := I + 1;
  2042.               STR132.BODY[I] := STRING_POOL^.CHARS[K];
  2043.           END;
  2044.           STR132.LENGTH := I;
  2045.       END
  2046.       ELSE
  2047.       BEGIN
  2048.           WRITELN (OUTPUT, 'SP_EXTR_STR: ',
  2049.                            'System Failure... Call maintenance.');
  2050.           CLIP_STOP;
  2051.       END (*IF.IF*);
  2052.   END;
  2053.  
  2054.   (*********************************************************************)
  2055.   (* Routine:     SP_GET_CHAR                                          *)
  2056.   (* Purpose:     Get character from given position of a string.       *)
  2057.   (* Interface:   INDEX   -   Index of the wanted character.           *)
  2058.   (*              STR     -   String to be searched.                   *)
  2059.   (*              RETURNS -   Wanted character.                        *)
  2060.   (* SP vars:     STRING_POOL.                                         *)
  2061.   (* MOD1:        EWvA (18/12/91) ivm probleem met SCAN_LINE (7).      *)
  2062.   (*********************************************************************)
  2063.   FUNCTION SP_GET_CHAR;
  2064.   BEGIN
  2065.       WITH STR DO
  2066.       BEGIN
  2067.           (* Check if value of INDEX is within correct range.          *)
  2068.           IF ((LAST - FIRST +1) < INDEX)
  2069.               OR (INDEX <= 0) THEN
  2070.           BEGIN
  2071.   (* MOD1:    WRITELN (OUTPUT, 'SP-GET_CHAR: ',                        *)
  2072.   (* MOD1:                    'System Failure... Call maintenance.');  *)
  2073.   (* MOD1:    CLIP_STOP;                                                *)
  2074.               SP_GET_CHAR := CHR(0);                          (* MOD1: *)
  2075.           END
  2076.           ELSE
  2077.               (* INDEX and STR are sound. Proceed to retrieve          *)
  2078.               (* character.                                            *)
  2079.               SP_GET_CHAR := STRING_POOL^.CHARS [FIRST + INDEX -1];
  2080.       END (*IF*)
  2081.   END (*SP_GET_CHAR*);
  2082.  
  2083.   (*********************************************************************)
  2084.   (* Routine:     SP_INIT                                              *)
  2085.   (* Purpose:     General initialization of the String Pool. It is     *)
  2086.   (*              only activated once at the start of an CLIP-run.      *)
  2087.   (*********************************************************************)
  2088.   PROCEDURE SP_INIT;
  2089.   BEGIN
  2090.       NEW (STRING_POOL);
  2091.       STRING_POOL^.USED := 0;
  2092.   END (*SP_INIT*);
  2093.  
  2094.   (*********************************************************************)
  2095.   (* Routine:     SP_INIT_STR                                          *)
  2096.   (* Purpose:     Initialize a string                                  *)
  2097.   (* Interface:   STR - the string to be initialized.                  *)
  2098.   (*********************************************************************)
  2099.   PROCEDURE SP_INIT_STR;
  2100.   BEGIN
  2101.       STR.FIRST := 0;
  2102.       STR.LAST  := -1;
  2103.   END (*SP_INIT_STR*);
  2104.  
  2105.   (*********************************************************************)
  2106.   (* Routine:     SP_IS_EMPTY_STR                                      *)
  2107.   (* Purpose:     The function examines if a string is empty or not.   *)
  2108.   (* Interface:   STR     -    string to be examined.                  *)
  2109.   (*              RETURNS -    TRUE if string is empty.                *)
  2110.   (*********************************************************************)
  2111.   FUNCTION SP_IS_EMPTY_STR;
  2112.   BEGIN
  2113.       SP_IS_EMPTY_STR := (SP_LENGTH_STR(STR) = 0);
  2114.   END (*SP_IS_EMPTY_STR*);
  2115.  
  2116.   (*********************************************************************)
  2117.   (* Routine:     SP_LENGTH_STR                                        *)
  2118.   (* Purpose:     To calculate the length of a string.                 *)
  2119.   (* Interface:   STR:    Given string.                                *)
  2120.   (*              RESULT: Length of STRING.                            *)
  2121.   (*********************************************************************)
  2122.   FUNCTION SP_LENGTH_STR;
  2123.   BEGIN
  2124.       SP_LENGTH_STR := STR.LAST - STR.FIRST + 1;
  2125.   END (*SP_LENGTH_STR*);
  2126.  
  2127.   (*********************************************************************)
  2128.   (* Routine:   SP_ADD_BUFFER                                          *)
  2129.   (* Purpose:   Add the buffer to a string.                            *)
  2130.   (* Interface: STR - String to which the buffer is added.             *)
  2131.   (* SP vars:   BUFFER                                                 *)
  2132.   (*********************************************************************)
  2133.   PROCEDURE SP_ADD_BUFFER;
  2134.   VAR
  2135.       I : INTEGER;
  2136.  
  2137.   BEGIN
  2138.       SP_INIT_STR (STR);
  2139.       FOR I := 1 TO BUFFER.LENGTH DO
  2140.           SP_ADD_CHAR (BUFFER.BODY[I], STR);
  2141.   END (*SP_ADD_BUFFER*);
  2142.  
  2143.   (*********************************************************************)
  2144.   (* Routine:   SP_ADD_BUFFER_CHAR                                     *)
  2145.   (* Purpose:   Add a character to the buffer.                         *)
  2146.   (* Interface: CH - Character to be added.                            *)
  2147.   (* SP vars:   BUFFER                                                 *)
  2148.   (*********************************************************************)
  2149.   PROCEDURE SP_ADD_BUFFER_CHAR;
  2150.   BEGIN
  2151.       WITH BUFFER DO
  2152.       IF LENGTH < 132 THEN
  2153.       BEGIN
  2154.           LENGTH := LENGTH + 1;
  2155.           BODY[LENGTH] := CH;
  2156.       END
  2157.       ELSE
  2158.       BEGIN
  2159.           WRITELN (OUTPUT,'SP_ADD_BUFFER_CHAR system failure...',
  2160.                           'Call maintenance');
  2161.           CLIP_STOP;
  2162.       END (*IF*);
  2163.   END (*SP_ADD_BUFFER_CHAR*);
  2164.  
  2165.   (*********************************************************************)
  2166.   (* Routine:   SP_GET_BUFFER_CHAR                                     *)
  2167.   (* Purpose:   Get a character from the buffer.                       *)
  2168.   (* Interface: INDEX -              Index of the wanted character.    *)
  2169.   (*            SP_GET_BUFFER_CHAR - Character to get.                 *)
  2170.   (* SP vars:   BUFFER                                                 *)
  2171.   (*********************************************************************)
  2172.   FUNCTION SP_GET_BUFFER_CHAR;
  2173.   BEGIN
  2174.       IF INDEX IN [1..BUFFER.LENGTH] THEN
  2175.           SP_GET_BUFFER_CHAR := BUFFER.BODY[INDEX]
  2176.       ELSE
  2177.           SP_GET_BUFFER_CHAR := CHR(0);
  2178.   END (*SP_GET_BUFFER_CHAR*);
  2179.  
  2180.   (*********************************************************************)
  2181.   (* Routine:   SP_INIT_BUFFER                                         *)
  2182.   (* Purpose:   Initialize the buffer by making it empty.              *)
  2183.   (* SP vars:   BUFFER                                                 *)
  2184.   (*********************************************************************)
  2185.   PROCEDURE SP_INIT_BUFFER;
  2186.   BEGIN
  2187.       BUFFER.LENGTH := 0;
  2188.   END (*SP_INIT_BUFFER*);
  2189.  
  2190.   (*-----------   DIAGNOSTic routines (ADT)  --------------------------*)
  2191.  
  2192.   (*********************************************************************)
  2193.   (* Routine:   DIAGNOST_INIT - INITialize the variables of DIAGNOST.  *)
  2194.   (* Purpose:   Initialize the global variables of procdure DIAG.      *)
  2195.   (* Interface: -                                                      *)
  2196.   (* DIAGNOST vars: DIAG_TBL, NO_MESSAGES, NR_MSG.                     *)
  2197.   (*********************************************************************)
  2198.   PROCEDURE DIAGNOST_INIT;
  2199.  
  2200.   VAR
  2201.       K:                INTEGER;
  2202.       TBL_FILE:         TEXT;
  2203.       ERROR_CODE:       INTEGER;
  2204.       DUMMY_ERROR:      INTEGER;
  2205.       DUMMY_FILE_OK :   BOOLEAN;
  2206.       DUMMY_ERROR_MSG : ERROR_MSG_;
  2207.       AUX_STRING_8:     PACKED ARRAY[1..8] OF CHAR;
  2208.       TBL_FILE_NAME:    FILE_SPEC_;
  2209.       MESS_CNT:         INTEGER;
  2210.       CH : CHAR;
  2211.  
  2212.  
  2213.   BEGIN
  2214.       (*******        DIAGNOST_INIT body                         *******)
  2215.       NO_MESSAGES := FALSE;
  2216.       NR_MSG := 0;
  2217.       FOR K := 1 TO MAX_NR_MESS DO
  2218.           DIAG_TBL[K].MESS_LOC := '                         ';
  2219.     
  2220.       (* Clear the variable which is to hold the specification of the  *)
  2221.       (* error message file.                                           *)
  2222.       TBL_FILE_NAME.BODY := EMPTY_STRING_FIXED;
  2223.       TBL_FILE_NAME.LENGTH := 0;
  2224.     
  2225.       (*******      DIAGNOST_INIT Add environment (TP) (#Opt)    *******)
  2226.     
  2227.       (* Write name of message file to TBL_FLE_NAME. The length must   *)
  2228.       (* be exactly 8 characters.                                      *)
  2229.       AUX_STRING_8 := 'CLIP_MSG';
  2230.       WITH TBL_FILE_NAME DO
  2231.       BEGIN
  2232.           FOR K := 1 TO 8 DO
  2233.               BODY[LENGTH+K] := AUX_STRING_8[K];
  2234.           LENGTH := LENGTH + 8;
  2235.       END (* WITH *);
  2236.     
  2237.       (*******      DIAGNOST_INIT Add extension (TP) (#Opt)      *******)
  2238.     
  2239.       EXT_FILE_PREP (TBL_FILE, TBL_FILE_NAME, INSP_MODE, DUMMY_FILE_OK,
  2240.                      ERROR_CODE, DUMMY_ERROR_MSG);
  2241.       IF ERROR_CODE <> 0 THEN
  2242.       BEGIN
  2243.           NO_MESSAGES := TRUE;
  2244.           WRITELN ('Error message file (logical name: CLIP_MSG) not found.');
  2245.           WRITELN ('CLiP will continue without diagnostics');
  2246.           WRITELN;
  2247.       END
  2248.       ELSE
  2249.       BEGIN
  2250.           NO_MESSAGES := FALSE;
  2251.     
  2252.           (*********************  DIAGNOST_INIT (1)  ***********************)
  2253.           (** Initialize DIAG_TBL by reading the TBL_FILE.                **)
  2254.           MESS_CNT := 1;
  2255.           WHILE NOT EOF (TBL_FILE) DO
  2256.           BEGIN
  2257.               WITH DIAG_TBL[MESS_CNT] DO
  2258.               BEGIN
  2259.                   (*********************  DIAGNOST_INIT (1.1)  *****************)
  2260.                   (** Initialize DIAG_TBL[MESS_CNT].MESS_LOC.                 **)
  2261.                   READ (TBL_FILE, CH);
  2262.                   READ (TBL_FILE, CH);
  2263.                   READ (TBL_FILE, CH);
  2264.                   K := 1;
  2265.                   WHILE CH <> ':' DO
  2266.                   BEGIN
  2267.                       MESS_LOC[K] := CH;
  2268.                       READ (TBL_FILE, CH);
  2269.                       K := K + 1;
  2270.                   END (*WHILE*);
  2271.                   (*****************  End of DIAGNOST_INIT (1.1)  **************)
  2272.         
  2273.                   (*********************  DIAGNOST_INIT (1.2)  *****************)
  2274.                   (** Initialize DIAG_TBL[MESS_CNT].MESSAGE.                  **)
  2275.                   MESSAGE := EMPTY_STRING_FIXED;
  2276.                   READ (TBL_FILE, CH);
  2277.                   MESS_L := 1;
  2278.                   WHILE CH <> '%' DO
  2279.                   BEGIN
  2280.                       IF EOLN (TBL_FILE) THEN
  2281.                           READLN (TBL_FILE);
  2282.                       READ (TBL_FILE, CH);
  2283.                       IF CH <> '%' THEN
  2284.                       BEGIN
  2285.                           MESSAGE[MESS_L] := CH;
  2286.                           MESS_L := MESS_L + 1;
  2287.                       END (*IF*);
  2288.                   END (*WHILE*);
  2289.                   (*****************  End of DIAGNOST_INIT (1.2)  **************)
  2290.         
  2291.                   READLN (TBL_FILE);
  2292.               END (*WITH*);
  2293.               MESS_CNT := MESS_CNT + 1;
  2294.           END (*WHILE*);
  2295.           (*****************  End of DIAGNOST_INIT (1)  ********************)
  2296.     
  2297.           (* Close the TBL_FILE and ignore any errors that may occur.      *)
  2298.           EXT_FILE_CLOSE (TBL_FILE, DUMMY_ERROR);
  2299.       END (*IF*);
  2300.       (*****************  End of DIAGNOST_INIT body  *******************)
  2301.  
  2302.   END (*DIAGNOST_INIT*);
  2303.  
  2304.   (*********************************************************************)
  2305.   (* Routine:     DIAG  -  Issue a DIAGnostic message.                 *)
  2306.   (* Purpose:     Handling of all diagnostics by a message to the      *)
  2307.   (*              terminal.                                            *)
  2308.   (* Interface:   DIAG_TBL -      Internal table with messages.        *)
  2309.   (*              MSG_TBL -       Internal table with detected errors. *)
  2310.   (*              NR_MSG -        Counting error messages in MSG_TBL.  *)
  2311.   (*              SEV -           Severity of the diagnostic.          *)
  2312.   (*              LOC -           Program location which detected the  *)
  2313.   (*                              problem.                             *)
  2314.   (*              SOURCE_LINE -   Source line causing the problem.     *)
  2315.   (*              SEGMENT -       Segment causing the problem.         *)
  2316.   (*              STRING132 -     Keyword(s) indicating the specific   *)
  2317.   (*                              diagnostic.                          *)
  2318.   (*********************************************************************)
  2319.   PROCEDURE DIAG (SEV:           SEV_CODE_;
  2320.                   LOC:           LOC_SPEC_;
  2321.                   SOURCE_LINE:   LINE_DES_;
  2322.                   SEGMENT:       SEGMENT_DES_;
  2323.                   STRING132:     STRING132_);
  2324.  
  2325.   VAR
  2326.       K :               INTEGER;
  2327.  
  2328.   BEGIN
  2329.       (*************************  DIAG (body)  *****************************)
  2330.       IF NOT NO_MESSAGES THEN
  2331.       BEGIN
  2332.           IF NR_MSG < MAX_ERROR THEN
  2333.           BEGIN
  2334.               NR_MSG := NR_MSG + 1;
  2335.     
  2336.               (*********************  DIAG (1)  ************************)
  2337.               (** Store the actual parameters passed to DIAG in       **)
  2338.               (** MSG_TBL[NR_MSG].                                    **)
  2339.               MSG_TBL[NR_MSG].SEV := SEV;
  2340.               MSG_TBL[NR_MSG].LOC := LOC;
  2341.               MSG_TBL[NR_MSG].STRING132 := STRING132;
  2342.               MSG_TBL[NR_MSG].SOURCE_LINE := SOURCE_LINE;
  2343.               MSG_TBL[NR_MSG].SEGMENT := SEGMENT;
  2344.               IF NOT ST_IS_EMPTY_SEG (SEGMENT) THEN
  2345.                       MSG_TBL[NR_MSG].LINE_ABS := ST_ABS_SEG (SEGMENT)
  2346.               ELSE IF FT_GET_LINE_LENGTH (SOURCE_LINE) > 0 THEN
  2347.                       MSG_TBL[NR_MSG].LINE_ABS :=
  2348.                               FT_ABS_LINE_NUMBER (SOURCE_LINE)
  2349.               ELSE
  2350.               BEGIN
  2351.                   WRITELN ('Internal error DIAG (1)... Call maintenance');
  2352.                   WRITELN ('Troubles caused by an error detected by:  ');
  2353.                   FOR K := 1 TO LOC_SPEC_L DO
  2354.                       WRITE (LOC[K]);
  2355.                   NR_MSG := NR_MSG - 1;
  2356.               END (*IF.IF*);
  2357.               (*******************  End of DIAG (1)  *******************)
  2358.           END
  2359.           ELSE IF NR_MSG = MAX_ERROR THEN
  2360.           BEGIN
  2361.               WRITELN (OUTPUT, 'CLIP detected more then ',
  2362.                                                        NR_MSG,' errors');
  2363.               WRITELN (OUTPUT, 'Only first ', NR_MSG,
  2364.                                ' diagnostic messages will be generated');
  2365.               NR_MSG := NR_MSG + 1;
  2366.           END
  2367.           ELSE IF NR_MSG > MAX_ERROR THEN
  2368.           BEGIN
  2369.               (* Nothing remains to be done here.                      *)
  2370.           END (*IF.IF.IF*);
  2371.       END (*IF*);
  2372.       (*********************  End of DIAG (body)  **********************)
  2373.  
  2374.   END (*DIAG*);
  2375.  
  2376.   (*********************************************************************)
  2377.   (* Routine:     DIAGNOST_EXIT - Exit the diagnostic table.           *)
  2378.   (* Purpose:     Generate the cumulated list of diagnostics to the    *)
  2379.   (*              termnal and, if specified, to a report file.         *)
  2380.   (* Interface:   DIAGNOST module variables                            *)
  2381.   (*              REPORT_FILE -   From CLIP_CDL                        *)
  2382.   (*              REPORT_OK -     From CLIP_CDL                        *)
  2383.   (*              RUN_INFO variables                                   *)
  2384.   (*********************************************************************)
  2385.   PROCEDURE DIAGNOST_EXIT;
  2386.  
  2387.   VAR
  2388.       I, K:           INTEGER;
  2389.       MESS_INDEX:   INTEGER;
  2390.       FILE_SPEC:      FILE_SPEC_;
  2391.       FIRST, LAST:    INTEGER;
  2392.       TMP_STRING_8:   PACKED ARRAY [1..8] OF CHAR;
  2393.       J:              INTEGER;
  2394.  
  2395.   BEGIN
  2396.       (*********************  DIAGNOST_EXIT (body)  ************************)
  2397.       IF NOT NO_MESSAGES THEN
  2398.       BEGIN
  2399.           IF NR_MSG > MAX_ERROR THEN
  2400.               NR_MSG := MAX_ERROR;
  2401.     
  2402.           (*****************  DIAGNOST_EXIT (1)  ***************************)
  2403.           (** Sort MSG_TBL by absolute line numbers.                      **)
  2404.           FOR K :=  NR_MSG DOWNTO 1 DO
  2405.           BEGIN
  2406.               FOR I := 1 TO K-1 DO
  2407.               BEGIN
  2408.                   IF MSG_TBL[I].LINE_ABS > MSG_TBL[I+1].LINE_ABS THEN
  2409.                   BEGIN
  2410.                       MSG_TBL[MAX_ERROR+1] := MSG_TBL[I];
  2411.                       MSG_TBL[I] := MSG_TBL[I+1];
  2412.                       MSG_TBL[I+1] := MSG_TBL[MAX_ERROR+1];
  2413.                   END (*IF*);
  2414.               END (*FOR*);
  2415.           END (*FOR*);
  2416.           (*****************  End of DIAGNOST_EXIT (1)  ********************)
  2417.     
  2418.           (* Write the opening lines of the report(s).                     *)
  2419.           IF NR_MSG > 0 THEN
  2420.           BEGIN
  2421.               WRITELN (OUTPUT, '============================ ',
  2422.                            'Diagnostics ===============================');
  2423.               IF REPORT_OK THEN
  2424.                   WRITELN (REPORT_FILE, '============================ ',
  2425.                            'Diagnostics ===============================');
  2426.           END (* IF *);
  2427.     
  2428.           (*****************  DIAGNOST_EXIT (2)  ***************************)
  2429.           (** Generate messages from MSG_TBL and DIAG_TBL to OUTPUT and   **)
  2430.           (** also to REPORT_FILE if REPORT_OK is raised. Write a         **)
  2431.           (** diagnostic in case of trouble, but do not abort.            **)
  2432.           FOR K := 1 TO NR_MSG DO
  2433.           BEGIN
  2434.               MESS_INDEX := 0;
  2435.         
  2436.               (*****************  DIAGNOST_EXIT (2.1)  *************************)
  2437.               (** Search DIAG_TBL for MSG_TBL[K].LOC. Store the index in      **)
  2438.               (** MESS_INDEX.                                                 **)
  2439.               FOR I := 1 TO MAX_NR_MESS DO
  2440.               BEGIN
  2441.                   IF DIAG_TBL[I].MESS_LOC = MSG_TBL[K].LOC THEN
  2442.                       MESS_INDEX := I;
  2443.               END (*FOR*);
  2444.               (****************  End of DIAGNOST_EXIT (2.1)  *******************)
  2445.         
  2446.               IF MESS_INDEX = 0 THEN
  2447.               BEGIN
  2448.                   WRITELN (OUTPUT,
  2449.                            'system error DIAGNOST_EXIT  ..... call maintenance');
  2450.                   WRITELN ('Not able to generate diagnostic message.');
  2451.                   WRITE ('DIAGNOST_EXIT was called by : ');
  2452.                   FOR I := 1 TO LOC_SPEC_L DO
  2453.                        WRITE (MSG_TBL[K].LOC[I]);
  2454.         
  2455.                   IF REPORT_OK THEN
  2456.                   BEGIN
  2457.                       WRITELN (REPORT_FILE,
  2458.                            'system error DIAGNOST_EXIT  ..... call maintenance');
  2459.                       WRITELN (REPORT_FILE,
  2460.                                      'Not able to generate diagnostic message.');
  2461.                       WRITE (REPORT_FILE, 'DIAGNOST_EXIT was called by : ');
  2462.                       FOR I := 1 TO LOC_SPEC_L DO
  2463.                           WRITE (REPORT_FILE, MSG_TBL[K].LOC[I]);
  2464.                   END (* IF *);
  2465.               END
  2466.               ELSE
  2467.               BEGIN
  2468.                   (*****************  DIAGNOST_EXIT (2.2)  *********************)
  2469.                   (** Generate diagnostic using information stored in MSG_-   **)
  2470.                   (** TBL[K] and DIAG_TBL[MESS_INDEX].                        **)
  2471.                   WITH MSG_TBL[K] DO
  2472.                   BEGIN
  2473.                       CASE SEV OF
  2474.                       WARN:
  2475.                           TMP_STRING_8 := 'Warning ';
  2476.                       ERR:
  2477.                           TMP_STRING_8 := 'Error   ';
  2478.                       FAIL:
  2479.                           TMP_STRING_8 := 'Failure ';
  2480.                       DUMP:
  2481.                           CLIP_STOP;
  2482.                       END (*CASE*);
  2483.                       WRITE (OUTPUT, TMP_STRING_8);
  2484.                       IF REPORT_OK THEN
  2485.                           WRITE (REPORT_FILE, TMP_STRING_8);
  2486.                 
  2487.                       IF NOT ST_IS_EMPTY_SEG (SEGMENT) THEN
  2488.                       BEGIN
  2489.                           ST_GET_SEG_RANGE (SEGMENT, FIRST, LAST);
  2490.                           ST_GET_FILE_SPEC (SEGMENT, FILE_SPEC);
  2491.                           WRITE (' between the lines ', FIRST:2, ' and ',
  2492.                                                    LAST:2, ' of file: ' );
  2493.                           FOR I := 1 TO FILE_SPEC.LENGTH DO
  2494.                               WRITE (FILE_SPEC.BODY[I]);
  2495.                           WRITELN;
  2496.                           WRITELN ('Source lines:');
  2497.                           WRITELN;
  2498.                 
  2499.                           (* Write segement to OUTPUT.                             *)
  2500.                           ST_WRITE_SEG (SEGMENT, 0, 0);
  2501.                           WRITELN;
  2502.                 
  2503.                           IF REPORT_OK THEN
  2504.                           BEGIN
  2505.                               WRITE (REPORT_FILE, ' between the lines ', FIRST:2,
  2506.                                                          ' and ', LAST:2, ' of file: ' );
  2507.                               FOR I := 1 TO FILE_SPEC.LENGTH DO
  2508.                                   WRITE (REPORT_FILE, FILE_SPEC.BODY[I]);
  2509.                               WRITELN (REPORT_FILE);
  2510.                               WRITELN (REPORT_FILE, 'Source lines:');
  2511.                               WRITELN (REPORT_FILE);
  2512.                 
  2513.                               (* Write segement to file variable REPORT_FILE of FT *)
  2514.                               (* (see also DIAGNOST_EXIT (2)).                     *)
  2515.                               ST_WRITE_SEG (SEGMENT, 0, 3);
  2516.                               WRITELN (REPORT_FILE);
  2517.                           END (* IF *);
  2518.                       END
  2519.                       ELSE IF FT_GET_LINE_LENGTH (SOURCE_LINE) > 0 THEN
  2520.                       BEGIN
  2521.                           FT_GET_FILE_SPEC (SOURCE_LINE, FILE_SPEC);
  2522.                 
  2523.                           WRITE ('in line ', FT_GET_LINE_NUMBER (SOURCE_LINE):4);
  2524.                           WRITE (' of file :');
  2525.                           FOR I := 1 TO FILE_SPEC.LENGTH DO
  2526.                               WRITE (FILE_SPEC.BODY[I]);
  2527.                           WRITELN;
  2528.                 
  2529.                           (* Write line to OUTPUT.                                 *)
  2530.                           FT_WRLN (SOURCE_LINE, 0, 0);
  2531.                 
  2532.                           IF REPORT_OK THEN
  2533.                           BEGIN
  2534.                               WRITE (REPORT_FILE, 'in line ',
  2535.                                                      FT_GET_LINE_NUMBER (SOURCE_LINE):4);
  2536.                               WRITE (REPORT_FILE, ' of file :');
  2537.                               FOR I := 1 TO FILE_SPEC.LENGTH DO
  2538.                                   WRITE (REPORT_FILE, FILE_SPEC.BODY[I]);
  2539.                               WRITELN (REPORT_FILE);
  2540.                 
  2541.                               (* Write LINE to file variable REPORT_FILE of FT     *)
  2542.                               (* (see also DIAGNOST_EXIT (2)).                     *)
  2543.                               FT_WRLN (SOURCE_LINE, 0, 3);
  2544.                           END (* IF *);
  2545.                       END
  2546.                       ELSE
  2547.                       BEGIN
  2548.                           WRITELN ('Internal error DIAG...  Call maintenance');
  2549.                           IF REPORT_OK THEN
  2550.                               WRITELN (REPORT_FILE,
  2551.                                              'Internal error DIAG...  Call maintenance');
  2552.                       END (*IF.IF*);
  2553.                       WITH DIAG_TBL[MESS_INDEX] DO
  2554.                       BEGIN
  2555.                           FOR I := 1 TO MESS_L DO
  2556.                           BEGIN
  2557.                               IF MESSAGE[I] <> '@' THEN
  2558.                               BEGIN
  2559.                                   WRITE (MESSAGE[I]);
  2560.                                   IF REPORT_OK THEN
  2561.                                       WRITE (REPORT_FILE, MESSAGE[I]);
  2562.                               END
  2563.                               ELSE
  2564.                               BEGIN
  2565.                                   FOR J := 1 TO STRING132.LENGTH DO
  2566.                                   BEGIN
  2567.                                       WRITE (STRING132.BODY[J]);
  2568.                                       IF REPORT_OK THEN
  2569.                                           WRITE (REPORT_FILE, STRING132.BODY[J]);
  2570.                                   END (*FOR*);
  2571.                               END (*IF*);
  2572.                           END (*FOR*);
  2573.                       END(*WITH*);
  2574.                   END (*WITH*);
  2575.                   (****************  End of DIAGNOST_EXIT (2.2)  ***************)
  2576.               END (*IF*);
  2577.               WRITELN; WRITELN;
  2578.               WRITELN ('------------------------------------',
  2579.                        '------------------------------------');
  2580.         
  2581.               IF REPORT_OK THEN
  2582.               BEGIN
  2583.                   WRITELN (REPORT_FILE); WRITELN (REPORT_FILE);
  2584.                   WRITELN (REPORT_FILE, '------------------------------------',
  2585.                                       '------------------------------------');
  2586.               END (* IF *);
  2587.           END (*FOR*);
  2588.           (****************  End of DIAGNOST_EXIT (2)  *********************)
  2589.     
  2590.           (* Write closing remarks of the report(s). Don't forget to close *)
  2591.           (* the REPORT_FILE if it has been used. Ignore closing problems. *)
  2592.           IF NR_MSG > 0 THEN
  2593.           BEGIN
  2594.               WRITE (OUTPUT, 'Diagnostics TOTAL of: ',NR_MSG:1);
  2595.               IF REPORT_OK THEN
  2596.                   WRITE (REPORT_FILE, 'Diagnostics TOTAL of: ',NR_MSG:1);
  2597.     
  2598.               (* Print different text to distinguish between a for single  *)
  2599.               (* error situation and a multiple error situation.           *)
  2600.               IF NR_MSG = 1 THEN
  2601.               BEGIN
  2602.                   WRITELN (' error or warning detected.');
  2603.                   IF REPORT_OK THEN
  2604.                       WRITELN (REPORT_FILE, ' error or warning detected.');
  2605.               END
  2606.               ELSE
  2607.               BEGIN
  2608.                   WRITELN (' errors or warnings detected.');
  2609.                   IF REPORT_OK THEN
  2610.                       WRITELN (REPORT_FILE, ' errors or warnings detected.');
  2611.               END (* IF *);
  2612.     
  2613.               WRITELN;
  2614.               WRITELN ('============================ End of ',
  2615.                        'diagnostics ========================');
  2616.               WRITELN;
  2617.               IF REPORT_OK THEN
  2618.               BEGIN
  2619.                   WRITELN (REPORT_FILE);
  2620.                   WRITELN (REPORT_FILE,
  2621.                                    '============================ End of ',
  2622.                              'diagnostics ========================');
  2623.                   WRITELN (REPORT_FILE);
  2624.               END (* IF *);
  2625.           END (*IF*);
  2626.       END (*IF*);
  2627.       (****************  End of DIAGNOST_EXIT (body)  **********************)
  2628.  
  2629.   END (*DIAG*);
  2630.  
  2631.  
  2632.   (*-----------   Main components of the CLiP system  -----------------*)
  2633.  
  2634.  
  2635.   (*********************************************************************)
  2636.   (* Routine:   SCN_LINE_INIT - INITialize variables of SCN_LINE.      *)
  2637.   (* Purpose:   Initialize the global variables of procedure SCAN_LINE.*)
  2638.   (* Interface: -                                                      *)
  2639.   (* SCN_LINE vars: ALLOWED                                            *)
  2640.   (*********************************************************************)
  2641.   PROCEDURE SCN_LINE_INIT;
  2642.   BEGIN
  2643.       ALLOWED := ['A'..'Z', 'a'..'z', '0'..'9','.'];
  2644.   END;
  2645.  
  2646.  
  2647.   (*********************************************************************)
  2648.   (* Routine:     SCAN_LINE  - Scan a source line                      *)
  2649.   (* Purpose:     To examine to what sort of CLIP category a source    *)
  2650.   (*              line belongs to.                                     *)
  2651.   (* Interface:   SOURCE_LINE:    The line to be scanned.              *)
  2652.   (*              LINE_INFO:      A record structure that holding all  *)
  2653.   (*                              relevant info of this SOURCE_LINE.   *)
  2654.   (*              RUN_INFO:       General information for this run.    *)
  2655.   (*********************************************************************)
  2656.   PROCEDURE SCAN_LINE (VAR LINE_INFO:   LINE_INFO_;
  2657.                        VAR SOURCE_LINE: LINE_DES_;
  2658.                        RUN_INFO:        RUN_INFO_);
  2659.  
  2660.   VAR
  2661.       SCAN_LINE_CONTINUE: BOOLEAN;
  2662.       L2_LINE,
  2663.       L3_LINE,
  2664.       L4_LINE:            BOOLEAN;
  2665.       LENGTH_LINE:        INTEGER;
  2666.       START_INDEX,
  2667.       END_INDEX:          INTEGER;
  2668.       SEGMENT:            SEGMENT_DES_;
  2669.       STRING132:          STRING132_;
  2670.       OPEN_FOUND,
  2671.       CLOSE_FOUND:        BOOLEAN;
  2672.       X, Y:               INTEGER;
  2673.       CH:                 CHAR;
  2674.       CLIP_CCL:    CHAR;
  2675.       CLIP_CCR:    CHAR;
  2676.  
  2677.   BEGIN
  2678.       (*******                SCAN_LINE (body)                   *******)
  2679.     
  2680.       (*************************  SCAN_LINE (1)  ***************************)
  2681.       (** Initialize the Buffer and SCAN_LINE_CONTINUE.                   **)
  2682.       SP_INIT_BUFFER;
  2683.       SCAN_LINE_CONTINUE := TRUE;
  2684.       (*********************  End of SCAN_LINE (1)  ************************)
  2685.     
  2686.       (*************************  SCAN_LINE (2)  ***************************)
  2687.       (** Examine the length of SOURCE_LINE. Make SCAN_LINE_CONTINUE to   **)
  2688.       (** FALSE if this length is shorter then that of CLIP_LPAR and      **)
  2689.       (** CLIP_RPAR together and set LINE_INFO.CATEGORY to L5.            **)
  2690.       WITH RUN_INFO DO
  2691.       BEGIN
  2692.           LENGTH_LINE := FT_GET_LINE_LENGTH (SOURCE_LINE);
  2693.           IF LENGTH_LINE < CLIP_LPAR.LENGTH+CLIP_RPAR.LENGTH THEN
  2694.           BEGIN
  2695.               LINE_INFO.CATEGORY := L5;
  2696.               SCAN_LINE_CONTINUE := FALSE;
  2697.           END (*IF*);
  2698.       END (*WITH*);
  2699.       (*********************  End of SCAN_LINE (2)  ************************)
  2700.     
  2701.       IF SCAN_LINE_CONTINUE THEN
  2702.       BEGIN
  2703.           (*************************  SCAN_LINE (3)  ***********************)
  2704.           (** Examine if SOURCE_LINE starts with an CLIP_LPAR and ends    **)
  2705.           (** with an CLIP_RPAR. Set SCAN_LINE_CONTINUE to FALSE if this  **)
  2706.           (** is not the case. Generate error message using SOURCE_LINE   **)
  2707.           (** if only one of the two strings is detected.                 **)
  2708.           X := 1;
  2709.           OPEN_FOUND := TRUE;
  2710.           WITH RUN_INFO DO
  2711.           BEGIN
  2712.               WHILE (X <= CLIP_LPAR.LENGTH) AND (SCAN_LINE_CONTINUE) DO
  2713.               BEGIN
  2714.                   CH := FT_GET_CHAR (SOURCE_LINE, X);
  2715.                   IF CLIP_LPAR.BODY[X] <> CH THEN
  2716.                   BEGIN
  2717.                       SCAN_LINE_CONTINUE := FALSE;
  2718.                       OPEN_FOUND := FALSE;
  2719.                   END (*IF*);
  2720.                X := X+1;
  2721.                END (*WHILE*);
  2722.         
  2723.                X := LENGTH_LINE-CLIP_RPAR.LENGTH+1;
  2724.                Y := 1;
  2725.                CLOSE_FOUND := TRUE;
  2726.                WHILE (X <=LENGTH_LINE) DO
  2727.                BEGIN
  2728.                    CH := FT_GET_CHAR (SOURCE_LINE, X);
  2729.                    IF CLIP_RPAR.BODY[Y] <> CH THEN
  2730.                    BEGIN
  2731.                        CLOSE_FOUND := FALSE;
  2732.                        SCAN_LINE_CONTINUE := FALSE;
  2733.                    END (*IF*);
  2734.                    X := X+1;
  2735.                    Y := Y+1;
  2736.                END (*WHILE*);
  2737.           END (*WITH*);
  2738.         
  2739.           IF NOT SCAN_LINE_CONTINUE THEN
  2740.           BEGIN
  2741.               ST_INIT_SEG (SEGMENT);
  2742.               STRING132.LENGTH := 0;
  2743.               STRING132.BODY   := EMPTY_STRING_FIXED;
  2744.               IF (OPEN_FOUND) AND (NOT CLOSE_FOUND) THEN
  2745.                   DIAG (WARN, 'SCAN_LINE (3a)           ', SOURCE_LINE, SEGMENT,
  2746.                         STRING132)
  2747.               ELSE IF (CLOSE_FOUND) AND (NOT OPEN_FOUND) THEN
  2748.                   DIAG (WARN, 'SCAN_LINE (3b)           ', SOURCE_LINE, SEGMENT,
  2749.                         STRING132);
  2750.           END (*WITH*);
  2751.           (*********************  End of SCAN_LINE (3)  ********************)
  2752.     
  2753.           IF NOT SCAN_LINE_CONTINUE THEN
  2754.               LINE_INFO.CATEGORY := L5
  2755.           ELSE
  2756.           BEGIN
  2757.               L3_LINE := FALSE;
  2758.     
  2759.               (*********************  SCAN_LINE (4)  ***********************)
  2760.               (** Examine the character following CLIP_LPAR and the one   **)
  2761.               (** preceeding CLIP_RPAR. Set L3_LINE to TRUE if at least   **)
  2762.               (** one of these characters differs from CLIP_CC. Generate  **)
  2763.               (** an error message using SOURCE_LINE if only one CLIP_CC  **)
  2764.               (** is detected.                                            **)
  2765.               WITH RUN_INFO DO
  2766.               BEGIN
  2767.                   X := CLIP_LPAR.LENGTH+1;
  2768.                   Y := LENGTH_LINE-CLIP_RPAR.LENGTH;
  2769.                   CLIP_CCL := FT_GET_CHAR (SOURCE_LINE, X);
  2770.                   CLIP_CCR := FT_GET_CHAR (SOURCE_LINE, Y);
  2771.             
  2772.                   IF (CLIP_CCL <> CLIP_CC) AND (CLIP_CCR <> CLIP_CC) THEN
  2773.                   BEGIN
  2774.                       SCAN_LINE_CONTINUE := FALSE;
  2775.                       L3_LINE := TRUE;
  2776.                   END
  2777.                   ELSE IF (CLIP_CCL<>CLIP_CC) AND (CLIP_CCR=CLIP_CC) THEN
  2778.                   BEGIN
  2779.                       ST_INIT_SEG (SEGMENT);
  2780.                       STRING132.LENGTH := 0;
  2781.                       STRING132.BODY := EMPTY_STRING_FIXED;
  2782.                       DIAG (WARN, 'SCAN_LINE (4a)           ', SOURCE_LINE, SEGMENT,
  2783.                             STRING132);
  2784.                       SCAN_LINE_CONTINUE := FALSE;
  2785.                       L3_LINE := TRUE;
  2786.                   END
  2787.                   ELSE IF (CLIP_CCL = CLIP_CC) AND (CLIP_CCR <> CLIP_CC) THEN
  2788.                   BEGIN
  2789.                       ST_INIT_SEG (SEGMENT);
  2790.                       STRING132.LENGTH := 0;
  2791.                       STRING132.BODY := EMPTY_STRING_FIXED;
  2792.                       DIAG (WARN, 'SCAN_LINE (4b)           ', SOURCE_LINE, SEGMENT,
  2793.                             STRING132);
  2794.                       SCAN_LINE_CONTINUE := FALSE;
  2795.                       L3_LINE := TRUE;
  2796.                   END (*IF.IF.IF*);
  2797.               END (*WITH*);
  2798.               (*****************  End of SCAN_LINE (4)  ********************)
  2799.     
  2800.               IF (L3_LINE) AND (LINE_INFO.OPTIONS) THEN
  2801.               BEGIN
  2802.                   (* SOURCE_LINE holds only options which will be      *)
  2803.                   (* scanned in a later stadium. Nothing remains to    *)
  2804.                   (* be done here.                                     *)
  2805.               END
  2806.               ELSE
  2807.               BEGIN
  2808.                   WITH RUN_INFO DO
  2809.                   BEGIN
  2810.                       START_INDEX := CLIP_LPAR.LENGTH;
  2811.                       END_INDEX :=
  2812.                       SOURCE_LINE.USED-RUN_INFO.CLIP_RPAR.LENGTH;
  2813.                   END (*WITH*);
  2814.                   L4_LINE := TRUE;
  2815.     
  2816.                   (*********************  SCAN_LINE (5)  *******************)
  2817.                   (** Examine the characters in SOURCE_LINE starting at   **)
  2818.                   (** START_INDEX until a character not equal to CLIP_CC  **)
  2819.                   (** or until END_INDEX is reached. If such a character  **)
  2820.                   (** is detected, set L4_LINE to FALSE and store its     **)
  2821.                   (** position in START_INDEX.                            **)
  2822.                   WHILE (START_INDEX < END_INDEX) AND (L4_LINE) DO
  2823.                   BEGIN
  2824.                       CH := FT_GET_CHAR (SOURCE_LINE, START_INDEX);
  2825.                       IF CH <> RUN_INFO.CLIP_CC THEN
  2826.                           L4_LINE := FALSE
  2827.                       ELSE
  2828.                           START_INDEX := START_INDEX+1;
  2829.                   END (*WHILE*);
  2830.                   (*****************  End of SCAN_LINE (5)  ****************)
  2831.     
  2832.                   IF NOT L4_LINE THEN
  2833.                   BEGIN
  2834.                       IF NOT L3_LINE THEN
  2835.                       LINE_INFO.OPTIONS := FALSE;
  2836.                       X := START_INDEX;
  2837.                       WHILE (X <= END_INDEX) AND (NOT LINE_INFO.OPTIONS) DO
  2838.                       BEGIN
  2839.                           CH := FT_GET_CHAR (SOURCE_LINE, X);
  2840.                           IF  (CH IN ALLOWED) OR
  2841.                               (CH=RUN_INFO.OPTION_MARKER) THEN
  2842.                           BEGIN
  2843.                               IF CH=RUN_INFO.OPTION_MARKER THEN
  2844.                               BEGIN
  2845.                                   LINE_INFO.OPTIONS := TRUE;
  2846.                                   SOURCE_LINE.POS_OPTION_MARKER := X;
  2847.                               END
  2848.                               ELSE
  2849.                               BEGIN
  2850.                                   (*************  SCAN_LINE (6)  ***********)
  2851.                                   (** Add CH to the Buffer String.        **)
  2852.                                   SP_ADD_BUFFER_CHAR (UC (CH));
  2853.                                   (*********  End of SCAN_LINE (6)  ********)
  2854.                               END (*IF*);
  2855.                           END (*IF*);
  2856.                           X := X+1;
  2857.                       END (*WHILE*);
  2858.                       L2_LINE := TRUE;
  2859.     
  2860.                       (*****************  SCAN_LINE (7)  *******************)
  2861.                       (** Check if the first LENGTH (CLIP_END) chars of   **)
  2862.                       (** the Bufffer String are equal to CLIP_END. If    **)
  2863.                       (** not, set L2_LINE to FALSE.                      **)
  2864.                       WITH RUN_INFO DO
  2865.                       BEGIN
  2866.                           X := 1;
  2867.                           WHILE (X <= CLIP_END.LENGTH) AND (SCAN_LINE_CONTINUE) DO
  2868.                           BEGIN
  2869.                               CH := SP_GET_BUFFER_CHAR (X);
  2870.                               IF UC (CLIP_END.BODY[X]) <> UC (CH) THEN
  2871.                                   L2_LINE := FALSE;
  2872.                               X := X+1;
  2873.                           END (*WHILE*);
  2874.                       END (*WITH*);
  2875.                       (***************  End of SCAN_LINE (7)  **************)
  2876.                   END (*IF*);
  2877.               END (*IF*);
  2878.               IF L4_LINE THEN
  2879.                   LINE_INFO.CATEGORY := L4
  2880.               ELSE IF L3_LINE THEN
  2881.                   LINE_INFO.CATEGORY := L3
  2882.               ELSE IF L2_LINE THEN
  2883.                   LINE_INFO.CATEGORY := L2
  2884.               ELSE
  2885.                   LINE_INFO.CATEGORY := L1;
  2886.           END (*IF*);
  2887.       END (*IF*);
  2888.       (*********************  End of SCAN_LINE (body)  *****************)
  2889.   END (*PROCEDURE SCAN_LINE*);
  2890.  
  2891.  
  2892.   (********************************************************************)
  2893.   (* Routine:     CONVERT_OPTION                                      *)
  2894.   (* Purpose:     Covert an abbreviated option to its full length.    *)
  2895.   (* Interface:   OPTION:     Option to be converted.                 *)
  2896.   (*              ERROR_CODE:  0 - No Problems.                       *)
  2897.   (*                           1 - No Match found.                    *)
  2898.   (*                          -1 - More then one match found.         *)
  2899.   (********************************************************************)
  2900.   PROCEDURE CONVERT_OPTION (VAR OPTION:     OPTION_KEYWORD_;
  2901.                             VAR ERROR_CODE: ERROR_CODE_);
  2902.  
  2903.   VAR
  2904.       K, I:           INTEGER;
  2905.       LENGTH_OPTION:  INTEGER;
  2906.       LOCATED:        BOOLEAN;
  2907.       DUMMY:          OPTION_KEYWORD_;
  2908.       NR_MATCH:       INTEGER;
  2909.  
  2910.   BEGIN
  2911.       DUMMY := EMPTY_OPTION;
  2912.       K := 1;
  2913.       NR_MATCH := 0;
  2914.       WHILE OPTION[K] <> ' ' DO
  2915.           K := K + 1;
  2916.       LENGTH_OPTION := K-1;
  2917.       LOCATED := FALSE;
  2918.       I := 1;
  2919.       ERROR_CODE := 1;                       (* Assume no match found. *)
  2920.       WHILE  (I <=  MAX_OPTIONS) DO
  2921.       BEGIN
  2922.           K := 1;
  2923.           LOCATED := TRUE;
  2924.           WHILE  (K <= LENGTH_OPTION) AND (LOCATED) DO
  2925.           BEGIN
  2926.               IF UC (OPTION[K]) = UC (OPTION_TABLE[I,K]) THEN
  2927.                   LOCATED :=  TRUE
  2928.               ELSE
  2929.                   LOCATED := FALSE;
  2930.               K := K + 1;
  2931.           END (*WHILE*);
  2932.  
  2933.           IF LOCATED THEN
  2934.           BEGIN
  2935.               IF NR_MATCH = 0 THEN
  2936.               BEGIN
  2937.                   ERROR_CODE := 0;        (* One match has been found. *)
  2938.                   DUMMY := OPTION_TABLE[I];
  2939.                   NR_MATCH := NR_MATCH + 1;
  2940.               END
  2941.               ELSE
  2942.                   ERROR_CODE := -1;       (* More then one match found *)
  2943.           END (*IF*);
  2944.           I := I + 1;
  2945.       END (*WHILE*);
  2946.       IF ERROR_CODE = 0 THEN
  2947.           OPTION := DUMMY;
  2948.   END (*CONVERT_OPTION*);
  2949.  
  2950.  
  2951.   (*********************************************************************)
  2952.   (* Routine:   SCN_OPTS_INIT - INITialize the variables of SCN_OPTS.  *)
  2953.   (* Purpose:   Initialize the global variables of SCAN_OPTIONS.       *)
  2954.   (* Interface: -                                                      *)
  2955.   (* SCN_OPTS vars: OPT_SPACE, DEFAULT_OPTIONS, OPT_CHARS,             *)
  2956.   (*                PASCAL_STRING, C_STRING.                           *)
  2957.   (*********************************************************************)
  2958.   PROCEDURE SCN_OPTS_INIT;
  2959.   BEGIN
  2960.       OPTION_TABLE [ 1]   :=  'QUICK          ';
  2961.       OPTION_TABLE [ 2]   :=  'MULTIPLE       ';
  2962.       OPTION_TABLE [ 3]   :=  'OPTIONAL       ';
  2963.       OPTION_TABLE [ 4]   :=  'FILE           ';
  2964.       OPTION_TABLE [ 5]   :=  'INDENT         ';
  2965.       OPTION_TABLE [ 6]   :=  'COMMENT        ';
  2966.       OPTION_TABLE [ 7]   :=  'OVERRULE       ';
  2967.       OPTION_TABLE [ 8]   :=  'LEADER         ';
  2968.       OPTION_TABLE [ 9]   :=  'TRAILER        ';
  2969.       OPTION_TABLE [10]   :=  'SEPARATOR      ';
  2970.       OPTION_TABLE [11]   :=  'DEFAULT        ';
  2971.       OPTION_TABLE [12]   :=  'LINENUMBER     ';
  2972.  
  2973.       OPT_CHARS := ['A'..'Z', 'a'..'z', '0'..'9', '"'];
  2974.  
  2975.       WITH DEFAULT_OPTIONS DO
  2976.       BEGIN
  2977.           QUICK           :=  FALSE;
  2978.           MULTIPLE        :=  FALSE;
  2979.           OPTIONAL        :=  FALSE;
  2980.           OVERRULE        :=  FALSE;
  2981.           LEADER          :=  FALSE;
  2982.           DEFAULT         :=  FALSE;
  2983.           TRAILER         :=  FALSE;
  2984.           SEPARATOR       :=  FALSE;
  2985.           LINENUMBER      :=  FALSE;
  2986.           SP_INIT_STR (FILE_NAME);
  2987.           SP_INIT_STR (INDENT);
  2988.           SP_INIT_STR (COMMENT);
  2989.       END;
  2990.  
  2991.       PASCAL_STRING := EMPTY_STRING_FIXED;
  2992.       PASCAL_STRING[1] := 'P';
  2993.       PASCAL_STRING[2] := 'A';
  2994.       PASCAL_STRING[3] := 'S';
  2995.       PASCAL_STRING[4] := 'C';
  2996.       PASCAL_STRING[5] := 'A';
  2997.       PASCAL_STRING[6] := 'L';
  2998.  
  2999.       FORTRAN_STRING := EMPTY_STRING_FIXED;
  3000.       FORTRAN_STRING[1] := 'F';
  3001.       FORTRAN_STRING[2] := 'O';
  3002.       FORTRAN_STRING[3] := 'R';
  3003.       FORTRAN_STRING[4] := 'T';
  3004.       FORTRAN_STRING[5] := 'R';
  3005.       FORTRAN_STRING[6] := 'A';
  3006.       FORTRAN_STRING[7] := 'N';
  3007.  
  3008.       C_STRING := EMPTY_STRING_FIXED;
  3009.       C_STRING[1] := 'C';
  3010.  
  3011.   END;
  3012.  
  3013.  
  3014.   (*********************************************************************)
  3015.   (* Routine:     SCAN_OPTIONS - SCAN OPTIONS                          *)
  3016.   (* Purpose:     To scan and store the options that are specified by  *)
  3017.   (*              a stub or slot segment.                              *)
  3018.   (* Interface:   SEGMENT_OPTIONS -   The structure with options.      *)
  3019.   (*              SEGMENT         -   The segment to be scanned.       *)
  3020.   (*              RUN_INFO        -   The information for this run.    *)
  3021.   (*              SEGMENT_TYPE    -   Type of segment to be scanned.   *)
  3022.   (*********************************************************************)
  3023.   PROCEDURE SCAN_OPTIONS (VAR SEGMENT_OPTIONS: OPTIONS_;
  3024.                               SEGMENT:         SEGMENT_DES_;
  3025.                               RUN_INFO:        RUN_INFO_;
  3026.                               SEGMENT_TYPE:    SEGMENT_TYPE_);
  3027.  
  3028.   VAR
  3029.       OPTION_KEYWORD:     OPTION_KEYWORD_;
  3030.       LINE:                LINE_DES_;
  3031.       SEGMENT_EXHAUSTED:   BOOLEAN;
  3032.       INDEX:          INTEGER;
  3033.       CH:             CHAR;
  3034.       LENGTH_LINE:    INTEGER;
  3035.       OK:  BOOLEAN;
  3036.       STRING132:      STRING132_;
  3037.       I:              INTEGER;
  3038.       ERROR_CODE:     ERROR_CODE_;
  3039.       DUMMY_LINE:     LINE_DES_;
  3040.       AUX_STRING10:   PACKED ARRAY[1..10] OF CHAR;
  3041.  
  3042.   BEGIN
  3043.       (*******                SCAN_OPTIONS (body)                *******)
  3044.  
  3045.       (*************************  SCAN_OPTIONS (1)  ********************)
  3046.       (** Initialize OPTION_KEYWORD. Make SEGMENT_OPTIONS equal to    **)
  3047.       (** DEFAULT_OPTIONS and set SEGMENT_EXHAUSTED to FALSE.         **)
  3048.       OPTION_KEYWORD     :=  EMPTY_OPTION;
  3049.       SEGMENT_OPTIONS    :=  DEFAULT_OPTIONS;
  3050.       SEGMENT_EXHAUSTED  :=  FALSE;
  3051.       (*********************  End of SCAN_OPTIONS (1)  *****************)
  3052.  
  3053.       IF NOT ST_IS_EMPTY_SEG (SEGMENT) THEN
  3054.       BEGIN
  3055.           (*********************  SCAN_OPTIONS (2)  ********************)
  3056.           (** Retrieve first line from SEGMENT which holds an option  **)
  3057.           (** marker and store it in LINE. Set SEGMENT_EXHAUSTED to   **)
  3058.           (** TRUE if no such LINE could be found.                    **)
  3059.           ST_GET_OPTION_LINE (SEGMENT, LINE);
  3060.           IF LINE.ID =0 THEN
  3061.               SEGMENT_EXHAUSTED := TRUE;
  3062.           (*****************  End of SCAN_OPTIONS (2)  *****************)
  3063.  
  3064.           WHILE NOT SEGMENT_EXHAUSTED DO
  3065.           BEGIN
  3066.               (*********************  SCAN_OPTIONS (3)  ****************)
  3067.               (** Scan LINE for options with their arguments and put  **)
  3068.               (** the result in SEGMENT_OPTIONS. Generate diagnostic  **)
  3069.               (** message using SEGMENT in case of trouble.           **)
  3070.               INDEX := FT_GET_POS_OPTION_MARKER (LINE);
  3071.               IF INDEX = 0 THEN
  3072.                   INDEX := RUN_INFO.CLIP_LPAR.LENGTH + 1;
  3073.               LENGTH_LINE := FT_GET_LINE_LENGTH (LINE) - RUN_INFO.CLIP_RPAR.LENGTH;
  3074.               CH := FT_GET_CHAR (LINE, INDEX);
  3075.               WHILE INDEX < LENGTH_LINE DO
  3076.               BEGIN
  3077.                   WHILE (CH <> RUN_INFO.OPTION_MARKER) AND
  3078.                                 (NOT  (CH IN OPT_CHARS)) AND
  3079.                                 (INDEX < LENGTH_LINE)  DO
  3080.                   BEGIN
  3081.                       INDEX := INDEX + 1;
  3082.                       CH := FT_GET_CHAR (LINE, INDEX);
  3083.                   END (*WHILE*);
  3084.             
  3085.                   IF CH = RUN_INFO.OPTION_MARKER THEN
  3086.                   BEGIN
  3087.                       (*********************  SCAN_OPTIONS (3.1)  ******************)
  3088.                       (** Start of a new option in LINE. Check by an empty        **)
  3089.                       (** OPTION_KEYWORD if previous option is "closed" correctly **)
  3090.                       (** and issue a diagnostic if not. Read the characters      **)
  3091.                       (** following OPTION_MARKER until the next OPT_SPACE and    **)
  3092.                       (** store them in OPTION_KEYWORD. Read a possible argument  **)
  3093.                       (** and update SEGMENT_OPTIONS. Initialize OPTION_KEYWORD   **)
  3094.                       (** if all went well.                                       **)
  3095.                       IF OPTION_KEYWORD <> EMPTY_OPTION THEN
  3096.                       BEGIN
  3097.                           (*********************  SCAN_OPTIONS (3.1.1)  ********************)
  3098.                           (** Missing argument of option stored in OPTION_KEYWORD.        **)
  3099.                           (** Generate a diagnostic using OPTION_KEYWORD and SEGMENT.     **)
  3100.                           STRING132.LENGTH := 0;
  3101.                           STRING132.BODY := EMPTY_STRING_FIXED;
  3102.                           FOR I := 1 TO MAX_OPTION_LENGTH DO
  3103.                           BEGIN
  3104.                               IF OPTION_KEYWORD[I] <> ' ' THEN
  3105.                               BEGIN
  3106.                                   STRING132.BODY[I] := OPTION_KEYWORD[I];
  3107.                                   STRING132.LENGTH :=  STRING132.LENGTH + 1;
  3108.                               END (*IF*);
  3109.                           END (*FOR*);
  3110.                           DIAG (ERR, 'SCAN_OPTIONS (3.1.1)     ', DUMMY_LINE, SEGMENT, STRING132);
  3111.                           OPTION_KEYWORD := EMPTY_OPTION;
  3112.                           (*****************  End of SCAN_OPTIONS (3.1.1)  *****************)
  3113.                       END (*IF*);
  3114.                       OK := FALSE;
  3115.                     
  3116.                       (*********************  SCAN_OPTIONS (3.1.2)  ************************)
  3117.                       (** Store all characters following this OPTION_MARKER in OPTION_-   **)
  3118.                       (** KEYWORD until the first character that is not a member of       **)
  3119.                       (** OPT_CHARS. Try to located the option in OPTION_TABLE and make   **)
  3120.                       (** OK equal to TRUE if a match is found and store the full option  **)
  3121.                       (** in OPTION_KEYWORD. In case no match can be found generate a     **)
  3122.                       (** diagnostic message and jump to the next option marker.          **)
  3123.                       INDEX := INDEX + 1;
  3124.                       CH := FT_GET_CHAR (LINE, INDEX);
  3125.                       WHILE NOT (CH IN OPT_CHARS)            AND
  3126.                             (CH <> RUN_INFO.OPTION_MARKER) AND
  3127.                               (INDEX < LENGTH_LINE)        DO
  3128.                       BEGIN
  3129.                           INDEX := INDEX + 1;
  3130.                           CH := FT_GET_CHAR (LINE, INDEX);
  3131.                       END (*WHILE*);
  3132.                       I := 1;
  3133.                       WHILE CH IN OPT_CHARS DO
  3134.                       BEGIN
  3135.                           OPTION_KEYWORD [I] := CH;
  3136.                           I := I + 1;
  3137.                           INDEX := INDEX + 1;
  3138.                           CH := FT_GET_CHAR (LINE, INDEX);
  3139.                       END (*WHILE*);
  3140.                       CONVERT_OPTION (OPTION_KEYWORD, ERROR_CODE);
  3141.                       IF ERROR_CODE <> 0 THEN
  3142.                       BEGIN
  3143.                           STRING132.LENGTH := 0;
  3144.                           STRING132.BODY := EMPTY_STRING_FIXED;
  3145.                           FOR I := 1 TO MAX_OPTION_LENGTH DO
  3146.                           BEGIN
  3147.                               IF OPTION_KEYWORD[I] <> ' ' THEN
  3148.                               BEGIN
  3149.                                   STRING132.BODY[I] := OPTION_KEYWORD[I];
  3150.                                   STRING132.LENGTH :=  STRING132.LENGTH + 1;
  3151.                               END (*IF*);
  3152.                           END (*FOR*);
  3153.                           IF ERROR_CODE = -1 THEN
  3154.                           BEGIN
  3155.                               (* More then one match found in table.                       *)
  3156.                               DIAG (ERR, 'SCAN_OPTIONS (3.1.2)a    ',
  3157.                                          DUMMY_LINE, SEGMENT, STRING132);
  3158.                               OPTION_KEYWORD := EMPTY_OPTION;
  3159.                           END
  3160.                           ELSE IF ERROR_CODE = 1 THEN
  3161.                           BEGIN
  3162.                               (* No match found in the table.                              *)
  3163.                               DIAG (ERR, 'SCAN_OPTIONS (3.1.2)b    ',
  3164.                                          DUMMY_LINE, SEGMENT, STRING132);
  3165.                               OPTION_KEYWORD := EMPTY_OPTION;
  3166.                           END (*IF.IF*);
  3167.                     
  3168.                           (* Jump to the next OPTION_MARKER in LINE.                       *)
  3169.                           WHILE (CH <> RUN_INFO.OPTION_MARKER) AND
  3170.                                 (INDEX<LENGTH_LINE)            DO
  3171.                           BEGIN
  3172.                               INDEX := INDEX + 1;
  3173.                               CH := FT_GET_CHAR (LINE, INDEX);
  3174.                           END (*WHILE*);
  3175.                       END
  3176.                       ELSE
  3177.                           OK := TRUE;
  3178.                       (*********************  End of SCAN_OPTIONS (3.1.2)  *****************)
  3179.                     
  3180.                       IF OK THEN
  3181.                       BEGIN
  3182.                           IF OPTION_KEYWORD = OPTION_TABLE[1] THEN
  3183.                           BEGIN
  3184.                               SEGMENT_OPTIONS.QUICK := TRUE;
  3185.                               OPTION_KEYWORD := EMPTY_OPTION;
  3186.                           END
  3187.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[2] THEN
  3188.                           BEGIN
  3189.                               SEGMENT_OPTIONS.MULTIPLE := TRUE;
  3190.                               OPTION_KEYWORD := EMPTY_OPTION;
  3191.                           END
  3192.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[3] THEN
  3193.                           BEGIN
  3194.                               SEGMENT_OPTIONS.OPTIONAL := TRUE;
  3195.                               OPTION_KEYWORD := EMPTY_OPTION;
  3196.                           END
  3197.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[4] THEN
  3198.                           BEGIN
  3199.                               (*****************  SCAN_OPTIONS (3.1.3)  ********************)
  3200.                               (** Add all characters from INDEX until the next member of  **)
  3201.                               (** OPT_SPACE to the string SEGMENT_OPTIONS.FILE_NAME.      **)
  3202.                               (** Generate a diagnostic message in case of trouble.       **)
  3203.                               WHILE  (NOT (CH IN OPT_CHARS)) AND
  3204.                                      (CH <> '"')           AND
  3205.                                      (INDEX<LENGTH_LINE)   DO
  3206.                               BEGIN
  3207.                                   INDEX := INDEX + 1;
  3208.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3209.                               END (*WHILE*);
  3210.                               IF CH = '"' THEN
  3211.                               BEGIN
  3212.                                   INDEX := INDEX + 1;
  3213.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3214.                                   WHILE  (CH <> '"') AND (INDEX < LENGTH_LINE) DO
  3215.                                   BEGIN
  3216.                               (*      SP_ADD_CHAR (UC (CH), SEGMENT_OPTIONS.FILE_NAME);  14/10/93) *)
  3217.                                       SP_ADD_CHAR (CH, SEGMENT_OPTIONS.FILE_NAME);
  3218.                                       INDEX := INDEX + 1;
  3219.                                       CH := FT_GET_CHAR (LINE, INDEX);
  3220.                                   END (*WHILE*);
  3221.                                   IF CH = '"' THEN
  3222.                                   BEGIN
  3223.                                       INDEX := INDEX + 1;
  3224.                                       CH := FT_GET_CHAR (LINE, INDEX);
  3225.                                   END
  3226.                                   ELSE
  3227.                                   BEGIN
  3228.                                       SP_EXTR_STR (SEGMENT_OPTIONS.FILE_NAME, STRING132);
  3229.                                       DIAG (ERR, 'SCAN_OPTIONS (3.1.3)a    ',
  3230.                                                  DUMMY_LINE, SEGMENT, STRING132);
  3231.                                       SP_INIT_STR (SEGMENT_OPTIONS.FILE_NAME);
  3232.                                       OPTION_KEYWORD := EMPTY_OPTION;
  3233.                                   END (*IF*);
  3234.                               END
  3235.                               ELSE IF (CH IN OPT_CHARS) THEN
  3236.                               BEGIN
  3237.                                   SP_EXTR_STR (SEGMENT_OPTIONS.FILE_NAME, STRING132);
  3238.                                   DIAG (ERR, 'SCAN_OPTIONS (3.1.3)b    ',
  3239.                                              DUMMY_LINE, SEGMENT, STRING132);
  3240.                                   SP_INIT_STR (SEGMENT_OPTIONS.FILE_NAME);
  3241.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3242.                             
  3243.                                   (* Jump to the next option marker.                       *)
  3244.                                   WHILE  (CH <> RUN_INFO.OPTION_MARKER) AND
  3245.                                          (INDEX<LENGTH_LINE)            DO
  3246.                                   BEGIN
  3247.                                       INDEX := INDEX + 1;
  3248.                                       CH := FT_GET_CHAR (LINE, INDEX);
  3249.                                   END (*WHILE*);
  3250.                               END
  3251.                               ELSE IF INDEX = LENGTH_LINE THEN
  3252.                               BEGIN
  3253.                                   (* The file specification must be on the next line.      *)
  3254.                                   (* Nothing remains to be done here.                      *)
  3255.                               END (* IF.IF.IF*);
  3256.                               (*****************  End of SCAN_OPTIONS (3.1.3)  *************)
  3257.                     
  3258.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.FILE_NAME) THEN
  3259.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3260.                           END
  3261.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[5] THEN
  3262.                           BEGIN
  3263.                               (*****************  SCAN_OPTIONS (3.1.4)  ********************)
  3264.                               (** Add all characters from INDEX until the next member of  **)
  3265.                               (** OPT_SPACE to the string SEGMENT_OPTIONS.INDENT. Give an **)
  3266.                               (** error and initialize SEGMENT_OPTIONS.INDENT and         **)
  3267.                               (** OPTION_KEYWORD and in case of trouble.                  **)
  3268.                               WHILE  (NOT  (CH IN OPT_CHARS)) AND
  3269.                                      (INDEX < LENGTH_LINE)  AND
  3270.                                      (CH <> RUN_INFO.OPTION_MARKER) DO
  3271.                               BEGIN
  3272.                                   INDEX := INDEX + 1;
  3273.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3274.                               END (*WHILE*);
  3275.                               WHILE (CH IN OPT_CHARS) AND (INDEX < LENGTH_LINE) DO
  3276.                               BEGIN
  3277.                                   SP_ADD_CHAR (UC (CH), SEGMENT_OPTIONS.INDENT);
  3278.                                   INDEX := INDEX + 1;
  3279.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3280.                               END (*WHILE*);
  3281.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.INDENT) THEN
  3282.                               BEGIN
  3283.                                   SP_EXTR_STR (SEGMENT_OPTIONS.INDENT, STRING132);
  3284.                                   IF  ((STRING132.BODY[1] <> 'O') OR
  3285.                                        (STRING132.BODY[2] <> 'N'))    AND
  3286.                                       ((STRING132.BODY[1] <> 'O') OR
  3287.                                        (STRING132.BODY[2] <> 'F') OR
  3288.                                        (STRING132.BODY[3] <> 'F'))    THEN
  3289.                                   BEGIN
  3290.                                       SP_INIT_STR (SEGMENT_OPTIONS.INDENT);
  3291.                                       OPTION_KEYWORD := EMPTY_OPTION;
  3292.                                       DIAG (ERR, 'SCAN_OPTIONS (3.1.4)     ',
  3293.                                                  DUMMY_LINE, SEGMENT, STRING132);
  3294.                                   END (*IF*);
  3295.                               END
  3296.                               ELSE
  3297.                               BEGIN
  3298.                                   (* The argument of the INDENT-option must be on the next *)
  3299.                                   (* line. Nothing remains to be done here.                *)
  3300.                               END (*IF*);
  3301.                               (*************  End of SCAN_OPTIONS (3.1.4)  *****************)
  3302.                     
  3303.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.INDENT) THEN
  3304.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3305.                           END
  3306.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[6] THEN
  3307.                           BEGIN
  3308.                               (*****************  SCAN_OPTIONS (3.1.5)  ********************)
  3309.                               (** Add all characters from INDEX until the next member of  **)
  3310.                               (** OPT_SPACE to SEGMENT_OPTIONS.COMMENT. Issue diagnostic  **)
  3311.                               (** and initialize OPTION_KEYWORD and SEGMENT_OPTIONS.-     **)
  3312.                               (** COMMENT in case of trouble.                             **)
  3313.                               WHILE  (NOT  (CH IN OPT_CHARS)) AND
  3314.                                      (INDEX < LENGTH_LINE)  AND
  3315.                                      (CH <> RUN_INFO.OPTION_MARKER) DO
  3316.                               BEGIN
  3317.                                   INDEX := INDEX + 1;
  3318.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3319.                               END (*WHILE*);
  3320.                               WHILE (CH IN OPT_CHARS) AND (INDEX < LENGTH_LINE) DO
  3321.                               BEGIN
  3322.                                   SP_ADD_CHAR (UC (CH), SEGMENT_OPTIONS.COMMENT);
  3323.                                   INDEX := INDEX + 1;
  3324.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3325.                               END (*WHILE*);
  3326.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.COMMENT) THEN
  3327.                               BEGIN
  3328.                                   SP_EXTR_STR (SEGMENT_OPTIONS.COMMENT, STRING132);
  3329.                                   IF  (STRING132.BODY = PASCAL_STRING)  OR
  3330.                                       (STRING132.BODY = FORTRAN_STRING) OR
  3331.                                       (STRING132.BODY = C_STRING) THEN
  3332.                                   BEGIN
  3333.                                        DIAG (WARN, 'SCAN_OPTIONS (3.1.5)a    ',
  3334.                                                    DUMMY_LINE, SEGMENT, STRING132);
  3335.                                        SP_INIT_STR (SEGMENT_OPTIONS.COMMENT);
  3336.                                        OPTION_KEYWORD := EMPTY_OPTION;
  3337.                                   END
  3338.                                   ELSE IF ((STRING132.BODY[1] <> 'O') OR
  3339.                                            (STRING132.BODY[2] <> 'N'))    AND
  3340.                                           ((STRING132.BODY[1] <> 'O') OR
  3341.                                            (STRING132.BODY[2] <> 'F') OR
  3342.                                            (STRING132.BODY[3] <> 'F'))    THEN
  3343.                                   BEGIN
  3344.                                       DIAG (ERR, 'SCAN_OPTIONS (3.1.5)b    ',
  3345.                                                  DUMMY_LINE, SEGMENT, STRING132);
  3346.                                       SP_INIT_STR (SEGMENT_OPTIONS.COMMENT);
  3347.                                       OPTION_KEYWORD := EMPTY_OPTION;
  3348.                                   END (*IF.IF*);
  3349.                               END
  3350.                               ELSE
  3351.                               BEGIN
  3352.                                   (* The argument of the option COMMENT must be on the     *)
  3353.                                   (* next line. Nothing remains to be done here            *)
  3354.                               END (*IF*);
  3355.                               (*************  End of SCAN_OPTIONS (3.1.5)  *****************)
  3356.                     
  3357.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.COMMENT) THEN
  3358.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3359.                           END
  3360.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[7] THEN
  3361.                           BEGIN
  3362.                               SEGMENT_OPTIONS.OVERRULE := TRUE;
  3363.                               OPTION_KEYWORD := EMPTY_OPTION;
  3364.                           END
  3365.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[8] THEN
  3366.                           BEGIN
  3367.                               SEGMENT_OPTIONS.LEADER := TRUE;
  3368.                               OPTION_KEYWORD := EMPTY_OPTION;
  3369.                           END
  3370.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[9] THEN
  3371.                           BEGIN
  3372.                               SEGMENT_OPTIONS.TRAILER := TRUE;
  3373.                               OPTION_KEYWORD := EMPTY_OPTION;
  3374.                           END
  3375.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[10] THEN
  3376.                           BEGIN
  3377.                               SEGMENT_OPTIONS.SEPARATOR := TRUE;
  3378.                               OPTION_KEYWORD := EMPTY_OPTION;
  3379.                           END
  3380.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[11] THEN
  3381.                           BEGIN
  3382.                               SEGMENT_OPTIONS.DEFAULT := TRUE;
  3383.                               OPTION_KEYWORD := EMPTY_OPTION;
  3384.                           END
  3385.                           ELSE IF OPTION_KEYWORD = OPTION_TABLE[12] THEN
  3386.                           BEGIN
  3387.                               SEGMENT_OPTIONS.LINENUMBER := TRUE;
  3388.                               OPTION_KEYWORD := EMPTY_OPTION;
  3389.                           END (*IF.IF.IF.IF.IF.IF.IF.IF.IF.IF.IF.IF*);
  3390.                       END (*IF*);
  3391.                       (*****************  End of SCAN_OPTIONS (3.1)  ***************)
  3392.                   END
  3393.                   ELSE IF CH IN OPT_CHARS THEN
  3394.                   BEGIN
  3395.                       (*********************  SCAN_OPTIONS (3.2)  ******************)
  3396.                       (** CH is only legal at this point as the first character   **)
  3397.                       (** of the argument of the previous option, i.e.            **)
  3398.                       (** OPTION_KEYWORD must not be empty. Read this argument.   **)
  3399.                       (** When problems arise, jump to next OPTION_MARKER and     **)
  3400.                       (** issue a diagnostic message.                             **)
  3401.                       IF OPTION_KEYWORD <> EMPTY_OPTION THEN
  3402.                       BEGIN
  3403.                           IF OPTION_KEYWORD = OPTION_TABLE[4] THEN
  3404.                           BEGIN
  3405.                               (*****************  SCAN_OPTIONS (3.2.1)  ********************)
  3406.                               (** Add characters from INDEX to SEGMENT_OPTIONS.FILE_NAME  **)
  3407.                               (** until the next OPT_SPACE is met. Diagnostic in case of  **)
  3408.                               (** trouble.                                                **)
  3409.                               WHILE  (NOT (CH IN OPT_CHARS)) AND
  3410.                                      (CH <> '"')           AND
  3411.                                      (INDEX < LENGTH_LINE) DO
  3412.                               BEGIN
  3413.                                   INDEX := INDEX + 1;
  3414.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3415.                               END (*WHILE*);
  3416.                               IF CH = '"' THEN
  3417.                               BEGIN
  3418.                                   INDEX := INDEX + 1;
  3419.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3420.                                   WHILE (CH <> '"') AND (INDEX <= LENGTH_LINE) DO
  3421.                                   BEGIN
  3422.                               (*      SP_ADD_CHAR (UC (CH), SEGMENT_OPTIONS.FILE_NAME);   14/10/93 *)
  3423.                                       SP_ADD_CHAR (CH, SEGMENT_OPTIONS.FILE_NAME);
  3424.                                       INDEX := INDEX + 1;
  3425.                                       CH := FT_GET_CHAR (LINE, INDEX);
  3426.                                   END (*WHILE*);
  3427.                                   IF CH='"' THEN
  3428.                                   BEGIN
  3429.                                       INDEX := INDEX + 1;
  3430.                                       CH := FT_GET_CHAR (LINE, INDEX);
  3431.                                   END
  3432.                                   ELSE
  3433.                                   BEGIN
  3434.                                       SP_EXTR_STR (SEGMENT_OPTIONS.FILE_NAME, STRING132);
  3435.                                       DIAG (ERR, 'SCAN_OPTIONS (3.2.1)a    ',
  3436.                                                  DUMMY_LINE, SEGMENT, STRING132);
  3437.                                       SP_INIT_STR (SEGMENT_OPTIONS.FILE_NAME);
  3438.                                       OPTION_KEYWORD := EMPTY_OPTION;
  3439.                                   END (*IF*);
  3440.                               END
  3441.                               ELSE IF (CH IN OPT_CHARS) THEN
  3442.                               BEGIN
  3443.                                   SP_EXTR_STR (SEGMENT_OPTIONS.FILE_NAME, STRING132);
  3444.                                   DIAG (ERR, 'SCAN_OPTIONS (3.2.1)b    ',
  3445.                                              DUMMY_LINE, SEGMENT, STRING132);
  3446.                                   SP_INIT_STR (SEGMENT_OPTIONS.FILE_NAME);
  3447.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3448.                             
  3449.                                   (* Jump to the next option marker.                       *)
  3450.                                   WHILE (CH <> RUN_INFO.OPTION_MARKER) AND
  3451.                                         (INDEX<LENGTH_LINE)            DO
  3452.                                   BEGIN
  3453.                                       INDEX := INDEX + 1;
  3454.                                       CH := FT_GET_CHAR (LINE, INDEX);
  3455.                                   END (*WHILE*);
  3456.                               END
  3457.                               ELSE IF INDEX=LENGTH_LINE THEN
  3458.                               BEGIN
  3459.                                   (* The file specification must be on the next line.      *)
  3460.                                   (* Nothing remains to be done here.                      *)
  3461.                               END (*IF.IF.IF*);
  3462.                               (*************  End of SCAN_OPTIONS (3.2.1)  *****************)
  3463.                     
  3464.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.FILE_NAME) THEN
  3465.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3466.                           END
  3467.                           ELSE IF OPTION_KEYWORD=OPTION_TABLE[5] THEN
  3468.                           BEGIN
  3469.                               (*****************  SCAN_OPTIONS (3.2.2)  ********************)
  3470.                               (** Add characters from INDEX to SEGMENT_OPTIONS.INDENT     **)
  3471.                               (** until the next OPT_SPACE is met. Generate a diagnostic  **)
  3472.                               (** message and reset OPTION_KEYWORD and SEGMENT_OPTIONS.-  **)
  3473.                               (** INDENT in case of trouble.                              **)
  3474.                               WHILE (NOT (CH IN OPT_CHARS)) AND
  3475.                                     (INDEX < LENGTH_LINE) DO
  3476.                               BEGIN
  3477.                                   INDEX := INDEX + 1;
  3478.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3479.                               END (*WHILE*);
  3480.                               WHILE (CH IN OPT_CHARS)     AND
  3481.                                     (INDEX<LENGTH_LINE) DO
  3482.                               BEGIN
  3483.                                   SP_ADD_CHAR (UC (CH), SEGMENT_OPTIONS.INDENT);
  3484.                                   INDEX := INDEX + 1;
  3485.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3486.                               END (*WHILE*);
  3487.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.INDENT) THEN
  3488.                               BEGIN
  3489.                                   SP_EXTR_STR (SEGMENT_OPTIONS.INDENT, STRING132);
  3490.                                   IF  ((STRING132.BODY[1] <> 'O') OR
  3491.                                        (STRING132.BODY[2] <> 'N'))    AND
  3492.                                       ((STRING132.BODY[1] <> 'O') OR
  3493.                                        (STRING132.BODY[2] <> 'F') OR
  3494.                                        (STRING132.BODY[3] <> 'F'))    THEN
  3495.                                   BEGIN
  3496.                                       SP_INIT_STR (SEGMENT_OPTIONS.INDENT);
  3497.                                       OPTION_KEYWORD := EMPTY_OPTION;
  3498.                                       DIAG (ERR, 'SCAN_OPTIONS (3.2.2)     ',
  3499.                                                  DUMMY_LINE, SEGMENT, STRING132);
  3500.                                   END (*IF*);
  3501.                               END
  3502.                               ELSE
  3503.                               BEGIN
  3504.                                   (* The argument of the option INDENT must be on the next *)
  3505.                                   (* line. Nothing remains to be done here                 *)
  3506.                               END (*IF*);
  3507.                               (*************  End of SCAN_OPTIONS (3.2.2)  *****************)
  3508.                     
  3509.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.INDENT) THEN
  3510.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3511.                           END
  3512.                           ELSE IF OPTION_KEYWORD=OPTION_TABLE[6] THEN
  3513.                           BEGIN
  3514.                               (*****************  SCAN_OPTIONS (3.2.3)  ********************)
  3515.                               (** Add characters from INDEX to SEGMENT_OPTIONS.COMMENT    **)
  3516.                               (** until the next OPT_SPACE is met. Generate a diagnostic  **)
  3517.                               (** message and reset OPTION_KEYWORD and SEGMENT_OPTIONS.-  **)
  3518.                               (** COMMENT in case of trouble.                             **)
  3519.                               WHILE (NOT (CH IN OPT_CHARS)) AND
  3520.                                     (INDEX<LENGTH_LINE)   DO
  3521.                               BEGIN
  3522.                                   INDEX := INDEX + 1;
  3523.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3524.                               END (*WHILE*);
  3525.                               WHILE (CH IN OPT_CHARS)     AND
  3526.                                     (INDEX<LENGTH_LINE) DO
  3527.                               BEGIN
  3528.                                   SP_ADD_CHAR (UC (CH), SEGMENT_OPTIONS.COMMENT);
  3529.                                   INDEX := INDEX + 1;
  3530.                                   CH := FT_GET_CHAR (LINE, INDEX);
  3531.                               END (*WHILE*);
  3532.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.COMMENT) THEN
  3533.                               BEGIN
  3534.                                   SP_EXTR_STR (SEGMENT_OPTIONS.COMMENT, STRING132);
  3535.                                   IF (STRING132.BODY = PASCAL_STRING) OR
  3536.                                      (STRING132.BODY = FORTRAN_STRING) OR
  3537.                                      (STRING132.BODY = C_STRING) THEN
  3538.                                   BEGIN
  3539.                                        DIAG (WARN, 'SCAN_OPTIONS (3.2.3)a    ',
  3540.                                                    DUMMY_LINE, SEGMENT, STRING132);
  3541.                                        SP_INIT_STR (SEGMENT_OPTIONS.COMMENT);
  3542.                                        OPTION_KEYWORD := EMPTY_OPTION;
  3543.                                   END
  3544.                                   ELSE IF ((STRING132.BODY[1] <> 'O') OR
  3545.                                            (STRING132.BODY[2] <> 'N'))    AND
  3546.                                           ((STRING132.BODY[1] <> 'O') OR
  3547.                                            (STRING132.BODY[2] <> 'F') OR
  3548.                                            (STRING132.BODY[3] <> 'F'))    THEN
  3549.                                   BEGIN
  3550.                                       DIAG (ERR, 'SCAN_OPTIONS (3.2.3)b    ',
  3551.                                                  DUMMY_LINE, SEGMENT, STRING132);
  3552.                                       SP_INIT_STR (SEGMENT_OPTIONS.COMMENT);
  3553.                                       OPTION_KEYWORD := EMPTY_OPTION;
  3554.                                   END (*IF.IF*);
  3555.                               END
  3556.                               ELSE
  3557.                               BEGIN
  3558.                                   (* The argument of the option COMMENT must be on the     *)
  3559.                                   (* next line. Nothing remains to be done here            *)
  3560.                               END (*IF*);
  3561.                               (*************  End of SCAN_OPTIONS (3.2.3)  *****************)
  3562.                               IF NOT SP_IS_EMPTY_STR (SEGMENT_OPTIONS.COMMENT) THEN
  3563.                                   OPTION_KEYWORD := EMPTY_OPTION;
  3564.                           END (*IF.IF.IF*);
  3565.                       END
  3566.                       ELSE
  3567.                       BEGIN
  3568.                           (*********************  SCAN_OPTIONS (3.2.4)  ********************)
  3569.                           (** Character is illegal at this position. Skip to next         **)
  3570.                           (** OPTION_MARKER or to end of this line. Generate a diagnostic **)
  3571.                           (** message using SEGMENT and LINE.                             **)
  3572.                           STRING132.LENGTH := 1;
  3573.                           STRING132.BODY[1] := CH;
  3574.                           DIAG (ERR, 'SCAN_OPTIONS (3.2.4)     ', DUMMY_LINE, SEGMENT, STRING132);
  3575.                           OPTION_KEYWORD := EMPTY_OPTION;
  3576.                           WHILE  (CH <> RUN_INFO.OPTION_MARKER) AND
  3577.                                  (INDEX < LENGTH_LINE)          DO
  3578.                           BEGIN
  3579.                               INDEX := INDEX + 1;
  3580.                               CH := FT_GET_CHAR (LINE, INDEX);
  3581.                           END (*WHILE*);
  3582.                           (*****************  End of SCAN_OPTIONS (3.2.4)  *****************)
  3583.                       END (*IF*);
  3584.                       (*****************  End of SCAN_OPTIONS (3.2)  ***************)
  3585.                   END (*IF*);
  3586.               END (*WHILE*);
  3587.               (*****************  End of SCAN_OPTIONS (3)  *************)
  3588.  
  3589.               (*****************  SCAN_OPTIONS (4)  ********************)
  3590.               (** Retrieve next LINE from SEGMENT. SEGMENT_EXHAUSTED  **)
  3591.               (** becomes TRUE if the segment is exhausted.           **)
  3592.               ST_GET_LINE (LINE);
  3593.               IF LINE.ID = 0 THEN
  3594.                   SEGMENT_EXHAUSTED := TRUE;
  3595.               (*************  End of SCAN_OPTIONS (4)  *****************)
  3596.           END (*WHILE*);
  3597.           IF SEGMENT_EXHAUSTED THEN
  3598.           BEGIN
  3599.               (*****************  SCAN_OPTIONS (5)  ********************)
  3600.               (** Check SEGMENT_OPTIONS for any errors. and generate  **)
  3601.               (** diagnostic message using SEGMENT if appropriate.    **)
  3602.               FT_INIT_LINE (DUMMY_LINE);
  3603.             
  3604.               (* 1. Check for a missing argument of the last option.   *)
  3605.               (*    This can be detected by a non-empty OPTION_KEYWORD.*)
  3606.               IF OPTION_KEYWORD <> EMPTY_OPTION THEN
  3607.               BEGIN
  3608.                   STRING132.LENGTH := 0;
  3609.                   STRING132.BODY := EMPTY_STRING_FIXED;
  3610.                   FOR I := 1 TO MAX_OPTION_LENGTH DO
  3611.                   BEGIN
  3612.                       IF OPTION_KEYWORD[I] <> ' ' THEN
  3613.                       BEGIN
  3614.                           STRING132.BODY[I] := OPTION_KEYWORD[I];
  3615.                           STRING132.LENGTH :=  STRING132.LENGTH + 1;
  3616.                       END (*IF*);
  3617.                   END (*FOR*);
  3618.                   DIAG (ERR, 'SCAN_OPTIONS (5a)        ', DUMMY_LINE, SEGMENT, STRING132);
  3619.               END (*IF*);
  3620.             
  3621.               (* 2. Check the use of stub options in a slot SEGMENT.   *)
  3622.               IF (SEGMENT_TYPE = SLOT) OR (SEGMENT_TYPE = CODE) THEN
  3623.               BEGIN
  3624.                   IF SEGMENT_OPTIONS.QUICK THEN
  3625.                   BEGIN
  3626.                       SEGMENT_OPTIONS.QUICK := FALSE;
  3627.                       STRING132.BODY[1] := 'Q';
  3628.                       STRING132.BODY[2] := 'U';
  3629.                       STRING132.BODY[3] := 'I';
  3630.                       STRING132.BODY[4] := 'C';
  3631.                       STRING132.BODY[5] := 'K';
  3632.                       STRING132.LENGTH := 5;
  3633.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3634.                             STRING132);
  3635.                   END (*IF*);
  3636.                   IF NOT  (SP_IS_EMPTY_STR (SEGMENT_OPTIONS.FILE_NAME)) THEN
  3637.                   BEGIN
  3638.                       SP_INIT_STR (SEGMENT_OPTIONS.FILE_NAME);
  3639.                       STRING132.BODY[1] := 'F';
  3640.                       STRING132.BODY[2] := 'I';
  3641.                       STRING132.BODY[3] := 'L';
  3642.                       STRING132.BODY[4] := 'E';
  3643.                       STRING132.LENGTH := 4;
  3644.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3645.                             STRING132);
  3646.                   END (*IF*);
  3647.                   IF SEGMENT_OPTIONS.OVERRULE THEN
  3648.                   BEGIN
  3649.                       SEGMENT_OPTIONS.OVERRULE := FALSE;
  3650.                       AUX_STRING10 := 'OVERRULE  ';
  3651.                       FOR I:= 1 TO 8 DO
  3652.                           STRING132.BODY[I] := AUX_STRING10[I];
  3653.                       STRING132.LENGTH := 8;
  3654.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3655.                             STRING132);
  3656.                   END (*IF*);
  3657.                   IF SEGMENT_OPTIONS.LEADER THEN
  3658.                   BEGIN
  3659.                       SEGMENT_OPTIONS.LEADER := FALSE;
  3660.                       AUX_STRING10 := 'LEADER    ';
  3661.                       FOR I := 1 TO 6 DO
  3662.                       STRING132.BODY[I] := AUX_STRING10[I];
  3663.                       STRING132.LENGTH := 6;
  3664.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3665.                             STRING132);
  3666.                   END (*IF*);
  3667.                   IF SEGMENT_OPTIONS.TRAILER THEN
  3668.                   BEGIN
  3669.                       SEGMENT_OPTIONS.TRAILER := FALSE;
  3670.                       AUX_STRING10 := 'TRAILER   ';
  3671.                       FOR I:= 1 TO 7 DO
  3672.                           STRING132.BODY[I] := AUX_STRING10[I];
  3673.                       STRING132.LENGTH := 7;
  3674.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3675.                             STRING132);
  3676.                   END (*IF*);
  3677.                   IF SEGMENT_OPTIONS.SEPARATOR THEN
  3678.                   BEGIN
  3679.                       SEGMENT_OPTIONS.SEPARATOR := FALSE;
  3680.                       AUX_STRING10 := 'SEPARATOR ';
  3681.                       FOR I := 1 TO 9 DO
  3682.                           STRING132.BODY[I] := AUX_STRING10[I];
  3683.                       STRING132.LENGTH := 9;
  3684.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3685.                             STRING132);
  3686.                   END (*IF*);
  3687.                   IF SEGMENT_OPTIONS.DEFAULT THEN
  3688.                   BEGIN
  3689.                       SEGMENT_OPTIONS.QUICK := FALSE;
  3690.                       AUX_STRING10 := 'DEFAULT   ';
  3691.                       FOR I := 1 TO 7 DO
  3692.                           STRING132.BODY[I] := AUX_STRING10[I];
  3693.                       STRING132.LENGTH := 7;
  3694.                       DIAG (ERR, 'SCAN_OPTIONS (5b)        ', DUMMY_LINE, SEGMENT,
  3695.                             STRING132);
  3696.                   END (*IF*);
  3697.               END
  3698.             
  3699.               (* 3. Check the use of slot options in a stub segment.   *)
  3700.               ELSE IF SEGMENT_TYPE = STUB THEN
  3701.               BEGIN
  3702.                   IF SEGMENT_OPTIONS.MULTIPLE THEN
  3703.                   BEGIN
  3704.                       SEGMENT_OPTIONS.MULTIPLE := FALSE;
  3705.                       AUX_STRING10 := 'MULTIPLE  ';
  3706.                       FOR I := 1 TO 8 DO
  3707.                           STRING132.BODY[I] := AUX_STRING10[I];
  3708.                       STRING132.LENGTH := 8;
  3709.                       DIAG (ERR, 'SCAN_OPTIONS (5c)        ', DUMMY_LINE, SEGMENT,
  3710.                             STRING132);
  3711.                   END (*IF*);
  3712.                   IF SEGMENT_OPTIONS.OPTIONAL THEN
  3713.                   BEGIN
  3714.                       SEGMENT_OPTIONS.OPTIONAL := FALSE;
  3715.                       AUX_STRING10 := 'OPTIONAL  ';
  3716.                       FOR I := 1 TO 8 DO
  3717.                           STRING132.BODY[I] := AUX_STRING10[I];
  3718.                       STRING132.LENGTH := 8;
  3719.                       DIAG (ERR, 'SCAN_OPTIONS (5c)        ', DUMMY_LINE, SEGMENT,
  3720.                             STRING132);
  3721.                   END (*IF*);
  3722.               END (*IF*);
  3723.             
  3724.               (* 4. Check illegal use of the options FILE, LEADER,     *)
  3725.               (*    TRAILER, SEPARATOR and DEFAULT in the segment.     *)
  3726.               WITH SEGMENT_OPTIONS DO
  3727.               BEGIN
  3728.                   IF  ( (NOT SP_IS_EMPTY_STR (FILE_NAME))                  AND
  3729.                       ( (DEFAULT) OR  (SEPARATOR) OR  (LEADER) OR  (TRAILER))) OR
  3730.                       ( (DEFAULT) AND  ( (SEPARATOR) OR  (LEADER) OR  (TRAILER))) OR
  3731.                       ( (LEADER) AND  ( (SEPARATOR) OR  (TRAILER)))  OR
  3732.                       ( (SEPARATOR) AND  (TRAILER)) THEN
  3733.                   BEGIN
  3734.                       DEFAULT := FALSE;
  3735.                       SEPARATOR := FALSE;
  3736.                       LEADER := FALSE;
  3737.                       TRAILER := FALSE;
  3738.                       STRING132.LENGTH := 0;
  3739.                       STRING132.BODY := EMPTY_STRING_FIXED;
  3740.                       DIAG (ERR, 'SCAN_OPTIONS (5d)        ', DUMMY_LINE, SEGMENT,
  3741.                             STRING132);
  3742.                   END (*IF*);
  3743.               END (*WITH*);
  3744.               (*****************  End of SCAN_OPTIONS (5)  *************)
  3745.           END (*IF*);
  3746.       END (*IF*);
  3747.       (*****************  End of SCAN_OPTIONS (body)  ******************)
  3748.  
  3749.   END (*PROCEDURE SCAN_OPTIONS*);
  3750.  
  3751.  
  3752.   (*********************************************************************)
  3753.   (* Routine:     BUILD_CODE_STRUCT - BUILD the structure CODE_STRUCT. *)
  3754.   (* Purpose:     Scan a stub block upon the different sort of         *)
  3755.   (*              segments and build the structure of stubs and slots. *)
  3756.   (* Interface:   CODE_STRUCT:  Anchors the datastructure representing *)
  3757.   (*                            the stubs and slots structure.         *)
  3758.   (*              RUN_INFO:     All information concerning this run.   *)
  3759.   (*              FIRST_LINE:   The first line of a stub block.        *)
  3760.   (*              LINE_INFO:    Scanned information of a line.         *)
  3761.   (*********************************************************************)
  3762.   PROCEDURE BUILD_CODE_STRUCT (VAR CODE_STRUCT:  CODE_STRUCT_;
  3763.                                    RUN_INFO:     RUN_INFO_;
  3764.                                    FIRST_LINE:   LINE_DES_;
  3765.                                    LINE_INFO:    LINE_INFO_);
  3766.  
  3767.   VAR
  3768.      SEGMENT_TYPE:    SEGMENT_TYPE_;
  3769.       END_OF_STUB_BLOCK:    BOOLEAN;
  3770.       SOURCE_LINE:          LINE_DES_;
  3771.       LAST_SLOT:  SLT_PTR_;
  3772.       STRING132:   STRING132_;
  3773.       SEGMENT:    SEGMENT_DES_;
  3774.  
  3775.   BEGIN
  3776.       (*******            BUILD_CODE_STRUCT (body)               *******)
  3777.  
  3778.       (*********************  BUILD_CODE_STRUCT (1)  *******************)
  3779.       (** FIRST_LINE marks a new stub segment. Link the stub into its **)
  3780.       (** position and let CODE_STRUCT.LAST_STUB refer to it. Set     **)
  3781.       (** LAST_SLOT to NIL. Initialize LAST_STUB. Add FIRST_LINE to   **)
  3782.       (** the segment LAST_STUB^.SRC_IMG. Use LINE_INFO to update     **)
  3783.       (** LAST_STUB^.NAME.                                            **)
  3784.       WITH CODE_STRUCT DO
  3785.       BEGIN
  3786.           LAST_SLOT := NIL;
  3787.           IF FIRST_STUB = NIL THEN
  3788.           BEGIN
  3789.               NEW (FIRST_STUB);
  3790.               LAST_STUB := FIRST_STUB;
  3791.           END
  3792.           ELSE
  3793.           BEGIN
  3794.               NEW (LAST_STUB^.NEXT_STUB);
  3795.               LAST_STUB := LAST_STUB^.NEXT_STUB;
  3796.           END (*IF*);
  3797.           WITH LAST_STUB^ DO
  3798.           BEGIN
  3799.               SLOTS := NIL;
  3800.               NEXT_STUB := NIL;
  3801.               NEXT_TWIN := NIL;
  3802.               ST_INIT_SEG (SRC_IMG);
  3803.               SP_INIT_STR (NAME);
  3804.               ST_PUT_SEG (FIRST_LINE, SRC_IMG);
  3805.               SP_ADD_BUFFER (LINE_INFO.LINE_ID);
  3806.               SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  3807.           END (*WITH*);
  3808.       END (*WITH*);
  3809.       (*****************  End of BUILD_CODE_STRUCT (1)  ****************)
  3810.  
  3811.       (* Set SEGMENT_TYPE to STUB since the first segment of a stub    *)
  3812.       (* block must be a stub segment. Initialize END_OF_STUB_BLOCK.   *)
  3813.       SEGMENT_TYPE := STUB;
  3814.       END_OF_STUB_BLOCK := FALSE;
  3815.  
  3816.       WHILE (NOT END_OF_STUB_BLOCK) AND (NOT FT_EOF) DO
  3817.       BEGIN
  3818.           FT_RDLN (SOURCE_LINE);
  3819.  
  3820.           (* Check wether or not we need to scan this line.            *)
  3821.           WITH RUN_INFO DO
  3822.           BEGIN
  3823.               IF FT_GET_LINE_LENGTH (SOURCE_LINE) >
  3824.                               CLIP_LPAR.LENGTH+CLIP_RPAR.LENGTH THEN
  3825.                   SCAN_LINE (LINE_INFO, SOURCE_LINE, RUN_INFO)
  3826.               ELSE
  3827.                   LINE_INFO.CATEGORY := L5;
  3828.           END (*WITH*);
  3829.  
  3830.           WITH CODE_STRUCT DO
  3831.           CASE LINE_INFO.CATEGORY OF
  3832.           L1:
  3833.               BEGIN
  3834.               IF LAST_SLOT = NIL THEN
  3835.               BEGIN
  3836.                   (*************  BUILD_CODE_STRUCT (2)  ***************)
  3837.                   (** The end of the previous stub segment. Scan the  **)
  3838.                   (** options of LAST_STUB^.SRC_IMG and store the     **)
  3839.                   (** found options in LAST_STUB^.OPTIONS. Add the    **)
  3840.                   (** buffer to LINE_INFO.LINE_ID.                    **)
  3841.                   WITH LAST_STUB^ DO
  3842.                       SCAN_OPTIONS (OPTIONS, SRC_IMG, RUN_INFO, SEGMENT_TYPE);
  3843.                   LINE_INFO.OPTIONS := FALSE;
  3844.                   SP_ADD_BUFFER (LINE_INFO.LINE_ID);
  3845.                   (*********  End of BUILD_CODE_STRUCT (2)  ************)
  3846.  
  3847.                   IF LAST_STUB^.OPTIONS.QUICK THEN
  3848.                   BEGIN
  3849.                       SEGMENT_TYPE := STUB;
  3850.                       (*************  BUILD_CODE_STRUCT (3)  ***********)
  3851.                       (** The end of the current stub block and the   **)
  3852.                       (** start a new one. Make an entry for this new **)
  3853.                       (** stub, let LAST_STUB point to it and initia- **)
  3854.                       (** lize its fields. Set LAST_SLOT to NIL. Add  **)
  3855.                       (** SOURCE_LINE to LAST_STUB^.SRC_IMG. Update   **)
  3856.                       (** LAST_STUB^.NAME with information from       **)
  3857.                       (** LINE_INFO.                                  **)
  3858.                       NEW (LAST_STUB^.NEXT_STUB);
  3859.                       LAST_STUB := LAST_STUB^.NEXT_STUB;
  3860.                       LAST_SLOT := NIL;
  3861.                       WITH LAST_STUB^ DO
  3862.                       BEGIN
  3863.                           SLOTS :=     NIL;
  3864.                           NEXT_STUB := NIL;
  3865.                           NEXT_TWIN := NIL;
  3866.                           ST_INIT_SEG (SRC_IMG);
  3867.                           SP_INIT_STR (NAME);
  3868.                           ST_PUT_SEG (SOURCE_LINE, SRC_IMG);
  3869.                           SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  3870.                       END (*WITH*);
  3871.                       (*********  End of BUILD_CODE_STRUCT (3)  ********)
  3872.                   END
  3873.                   ELSE
  3874.                   BEGIN
  3875.                       SEGMENT_TYPE :=  SLOT;
  3876.                       (*************  BUILD_CODE_STRUCT (4)  ***********)
  3877.                       (** First slot segment of this stub block. Make **)
  3878.                       (** entry for this new slot, let LAST_SLOT      **)
  3879.                       (** point to it and initialize its fields. Add  **)
  3880.                       (** SOURCE_LINE to segment LAST_SLOT^.SRC_IMG.  **)
  3881.                       (** Update LAST_SLOT with the information hold  **)
  3882.                       (** by LINE_INFO.                               **)
  3883.                       NEW (LAST_STUB^.SLOTS);
  3884.                       LAST_SLOT := LAST_STUB^.SLOTS;
  3885.                       WITH LAST_SLOT^ DO
  3886.                       BEGIN
  3887.                           SP_INIT_STR (NAME);
  3888.                           ST_INIT_SEG (SRC_IMG);
  3889.                           STUB_REF := NIL;
  3890.                           ST_INIT_SEG (CODE);
  3891.                           NEXT_SLOT := NIL;
  3892.                           ST_PUT_SEG (SOURCE_LINE, SRC_IMG);
  3893.                           SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  3894.                       END (*WITH*);
  3895.                       (*********  End of BUILD_CODE_STRUCT (4)  ********)
  3896.                   END (*IF*);
  3897.               END
  3898.               ELSE
  3899.               BEGIN
  3900.                   (*************  BUILD_CODE_STRUCT (5)  ***************)
  3901.                   (** End of the previous segment LAST_SLOT^.SRC_IMG. **)
  3902.                   (** Finish the segment by scanning its options      **)
  3903.                   (** using RUN_INFO. Store found options in          **)
  3904.                   (** LAST_SLOT^.OPTIONS. Add the buffer to LINE_-    **)
  3905.                   (** INFO.LINE_ID.                                   **)
  3906.                   WITH LAST_SLOT^ DO
  3907.                       SCAN_OPTIONS (OPTIONS, SRC_IMG, RUN_INFO, SEGMENT_TYPE);
  3908.                   LINE_INFO.OPTIONS := FALSE;
  3909.                   SP_ADD_BUFFER (LINE_INFO.LINE_ID);
  3910.                   (*********  End of BUILD_CODE_STRUCT (5)  ************)
  3911.                   IF LAST_STUB^.OPTIONS.QUICK THEN
  3912.                   BEGIN
  3913.                       SEGMENT_TYPE := STUB;
  3914.                       (*************  BUILD_CODE_STRUCT (6)  ***********)
  3915.                       (** End of current stub block and the start of  **)
  3916.                       (** a new one. Link this new stub into its po-  **)
  3917.                       (** sition, let LAST_STUB point to it and ini-  **)
  3918.                       (** tialize its fields. Add SOURCE_LINE to      **)
  3919.                       (** segment LAST_STUB^.SRC_IMG and update       **)
  3920.                       (** LAST_STUB^.NAME with the help of LINE_INFO. **)
  3921.                       NEW (LAST_STUB^.NEXT_STUB);
  3922.                       LAST_STUB := LAST_STUB^.NEXT_STUB;
  3923.                       LAST_SLOT := NIL;
  3924.                       WITH LAST_STUB^ DO
  3925.                       BEGIN
  3926.                           SLOTS :=     NIL;
  3927.                           NEXT_STUB := NIL;
  3928.                           NEXT_TWIN := NIL;
  3929.                           ST_INIT_SEG (SRC_IMG);
  3930.                           SP_INIT_STR (NAME);
  3931.                           ST_PUT_SEG (SOURCE_LINE, SRC_IMG);
  3932.                           SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  3933.                       END (*WITH*);
  3934.                       (*********  End of BUILD_CODE_STRUCT (6)  ********)
  3935.                   END
  3936.                   ELSE
  3937.                   BEGIN
  3938.                       SEGMENT_TYPE :=  SLOT;
  3939.                       (*************  BUILD_CODE_STRUCT (7)  ***********)
  3940.                       (** Start of a new slot segment. Link slot into **)
  3941.                       (** its position, let LAST_SLOT point to it and **)
  3942.                       (** initialize its fields. Add SOURCE_LINE to   **)
  3943.                       (** LAST_SLOT^.SRC_IMG and update LAST_SLOT^.-  **)
  3944.                       (** NAME with the help of LINE_INFO.            **)
  3945.                       NEW (LAST_SLOT^.NEXT_SLOT);
  3946.                       LAST_SLOT := LAST_SLOT^.NEXT_SLOT;
  3947.                       WITH LAST_SLOT^ DO
  3948.                       BEGIN
  3949.                           SP_INIT_STR (NAME);
  3950.                           ST_INIT_SEG (SRC_IMG);
  3951.                           STUB_REF := NIL;
  3952.                           ST_INIT_SEG (CODE);
  3953.                           NEXT_SLOT := NIL;
  3954.                           ST_PUT_SEG (SOURCE_LINE, SRC_IMG);
  3955.                           SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  3956.                       END (*WITH*);
  3957.                       (*********  End of BUILD_CODE_STRUCT (7)  ********)
  3958.                   END (*IF*);
  3959.               END(*IF*);
  3960.               END;
  3961.           L2:
  3962.               BEGIN
  3963.               (*****************  BUILD_CODE_STRUCT (8)  ***************)
  3964.               (** End of the previous slot or stub segment. Scan      **)
  3965.               (** LAST_<x>^.SRC_IMG for options and store them in     **)
  3966.               (** LAST_<x>^.OPTIONS. Add the buffer to LINE_INFO.-    **)
  3967.               (** LINE_ID after that. <x> reads "STUB" for a stub     **)
  3968.               (** and "SLOT" for a slot- or code-segment.             **)
  3969.               IF (SEGMENT_TYPE = STUB) THEN
  3970.               BEGIN
  3971.                   WITH LAST_STUB^ DO
  3972.                       SCAN_OPTIONS (OPTIONS, SRC_IMG, RUN_INFO, SEGMENT_TYPE)
  3973.               END
  3974.               ELSE
  3975.               BEGIN
  3976.                   WITH LAST_SLOT^ DO
  3977.                       SCAN_OPTIONS (OPTIONS, SRC_IMG, RUN_INFO, SEGMENT_TYPE);
  3978.               END (*IF*);
  3979.               LINE_INFO.OPTIONS := FALSE;
  3980.               SP_ADD_BUFFER (LINE_INFO.LINE_ID);
  3981.               (*************  End of BUILD_CODE_STRUCT (8)  ************)
  3982.  
  3983.               END_OF_STUB_BLOCK := TRUE;
  3984.               SEGMENT_TYPE := END_STUB;
  3985.  
  3986.               (*****************  BUILD_CODE_STRUCT (9)  ***************)
  3987.               (** Start of the end segment. Link slot into its posi-  **)
  3988.               (** tion, let LAST_SLOT point to it and initialize its  **)
  3989.               (** fields. Add SOURCE_LINE to the segment LAST_SLOT^.- **)
  3990.               (** SRC_IMG and update LAST_SLOT^.NAME using the infor- **)
  3991.               (** mation of LINE_INFO.                                **)
  3992.               IF LAST_SLOT<>NIL THEN
  3993.               BEGIN
  3994.                   NEW (LAST_SLOT^.NEXT_SLOT);
  3995.                   LAST_SLOT := LAST_SLOT^.NEXT_SLOT;
  3996.               END
  3997.               ELSE
  3998.               BEGIN
  3999.                   NEW (LAST_STUB^.SLOTS);
  4000.                   LAST_SLOT := LAST_STUB^.SLOTS;
  4001.               END (*IF*);
  4002.               WITH LAST_SLOT^ DO
  4003.               BEGIN
  4004.                   SP_INIT_STR (NAME);
  4005.                   ST_INIT_SEG (SRC_IMG);
  4006.                   STUB_REF := NIL;
  4007.                   ST_INIT_SEG (CODE);
  4008.                   NEXT_SLOT := NIL;
  4009.                   SCAN_OPTIONS (OPTIONS, SRC_IMG, RUN_INFO, SEGMENT_TYPE);
  4010.                   LINE_INFO.OPTIONS := FALSE;
  4011.                   ST_PUT_SEG (SOURCE_LINE, SRC_IMG);
  4012.                   SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  4013.               END; (*WITH*)
  4014.               (*************  End of BUILD_CODE_STRUCT (9)  ************)
  4015.               END;
  4016.           L3:
  4017.               BEGIN
  4018.               IF SEGMENT_TYPE = STUB THEN
  4019.               BEGIN
  4020.                   (*************  BUILD_CODE_STRUCT (10)  **************)
  4021.                   (** Continuation line of the stub segment. Add      **)
  4022.                   (** SOURCE_LINE to LAST_STUB^.SRC_IMG. Add buffer   **)
  4023.                   (** to LINE_INFO.LINE_ID and update LAST_STUB^.NAME **)
  4024.                   (** using LINE_INFO.                                **)
  4025.                   WITH LAST_STUB^ DO
  4026.                   BEGIN
  4027.                       ST_PUT_LINE (SOURCE_LINE, SRC_IMG);
  4028.                       SP_ADD_BUFFER (LINE_INFO.LINE_ID);
  4029.                       SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  4030.                   END (*WITH*);
  4031.                   (*********  End of BUILD_CODE_STRUCT (10)  ***********)
  4032.               END
  4033.               ELSE IF SEGMENT_TYPE = SLOT THEN
  4034.               BEGIN
  4035.                   (*************  BUILD_CODE_STRUCT (11)  **************)
  4036.                   (** Continuation of the current slot segment.       **)
  4037.                   (** Add SOURCE_LINE to LAST_SLOT^.SRC_IMG, add the  **)
  4038.                   (** buffer to LINE_INFO.LINE_ID and update LAST_-   **)
  4039.                   (** SLOT^.NAME using LINE_INFO.                     **)
  4040.                   WITH LAST_SLOT^ DO
  4041.                   BEGIN
  4042.                       ST_PUT_LINE (SOURCE_LINE, SRC_IMG);
  4043.                       SP_ADD_BUFFER (LINE_INFO.LINE_ID);
  4044.                       SP_CONC_STR (NAME, LINE_INFO.LINE_ID);
  4045.                   END (*WITH*);
  4046.                   (*********  End of BUILD_CODE_STRUCT (11)  ***********)
  4047.               END
  4048.               ELSE
  4049.               BEGIN
  4050.                   (*************  BUILD_CODE_STRUCT (12)  **************)
  4051.                   (** This orphan line cannot be paste to a stub- or  **)
  4052.                   (** slot-segment. Generate an error message using   **)
  4053.                   (** the information hold by SOURCE_LINE.            **)
  4054.                   ST_INIT_SEG (SEGMENT);
  4055.                   STRING132.LENGTH := 0;
  4056.                   STRING132.BODY := EMPTY_STRING_FIXED;
  4057.                   DIAG (WARN, 'BUILD_C_S (12)           ', SOURCE_LINE, SEGMENT, STRING132);
  4058.                   (*********  End of BUILD_CODE_STRUCT (12)  ***********)
  4059.               END (*IF.IF*);
  4060.               END;
  4061.           L4:
  4062.               BEGIN
  4063.               IF SEGMENT_TYPE = STUB THEN
  4064.               BEGIN
  4065.                   (*************  BUILD_CODE_STRUCT (13)  **************)
  4066.                   (** Continuation ofcurrent stub segment. Add        **)
  4067.                   (** SOURCE_LINE to segment LAST_STUB^.SRC_IMG.      **)
  4068.                   WITH LAST_STUB^ DO
  4069.                       ST_PUT_LINE (SOURCE_LINE, SRC_IMG);
  4070.                   (*********  End of BUILD_CODE_STRUCT (13)  ***********)
  4071.               END
  4072.               ELSE IF SEGMENT_TYPE = SLOT THEN
  4073.               BEGIN
  4074.                   (*************  BUILD_CODE_STRUCT (14)  **************)
  4075.                   (** Continuation of current slot segment. Add       **)
  4076.                   (** SOURCE_LINE to segment LAST_SLOT^.SRC_IMG.      **)
  4077.                   WITH LAST_SLOT^ DO
  4078.                       ST_PUT_LINE (SOURCE_LINE, SRC_IMG);
  4079.                   (*********  End of BUILD_CODE_STRUCT (14)  ***********)
  4080.               END
  4081.               ELSE IF SEGMENT_TYPE = CODE THEN
  4082.               BEGIN
  4083.                   (*************  BUILD_CODE_STRUCT (15)  **************)
  4084.                   (** Continuation of current code segment. Add       **)
  4085.                   (** SOURCE_LINE to segment LAST_SLOT^.CODE.         **)
  4086.                   WITH LAST_SLOT^ DO
  4087.                       ST_PUT_LINE (SOURCE_LINE, CODE);
  4088.                   (*********  End of BUILD_CODE_STRUCT (15)  ***********)
  4089.               END (*IF.IF.IF*);
  4090.               END;
  4091.           L5:
  4092.               BEGIN
  4093.               IF SEGMENT_TYPE = STUB THEN
  4094.               BEGIN
  4095.                   (*************  BUILD_CODE_STRUCT (16)  **************)
  4096.                   (** End of previous stub segment LAST_STUB^.-       **)
  4097.                   (** SRC_IMG. Complete that segment by scanning      **)
  4098.                   (** which are stored to LAST_STUB^.OPTIONS.         **)
  4099.                   WITH LAST_STUB^ DO
  4100.                       SCAN_OPTIONS (OPTIONS, SRC_IMG, RUN_INFO, SEGMENT_TYPE);
  4101.                   LINE_INFO.OPTIONS := FALSE;
  4102.                   (*********  End of BUILD_CODE_STRUCT (16)  ***********)
  4103.  
  4104.                   IF (LAST_STUB^.OPTIONS.QUICK) AND
  4105.                       (FT_GET_LINE_LENGTH (SOURCE_LINE) = 0) THEN
  4106.                   BEGIN
  4107.                       (*************  BUILD_CODE_STRUCT (17)  **********)
  4108.                       (** End of current stub block. Set Boolean      **)
  4109.                       (** END_OF_STUB_BLOCK to TRUE.                  **)
  4110.                       END_OF_STUB_BLOCK := TRUE;
  4111.                       (*********  End of BUILD_CODE_STRUCT (17)  *******)
  4112.                   END
  4113.                   ELSE
  4114.                   BEGIN
  4115.                       SEGMENT_TYPE := CODE;
  4116.                       (*************  BUILD_CODE_STRUCT (18)  **********)
  4117.                       (** Start of a new code-segment. Link a new     **)
  4118.                       (** entry for this slot into its position. Let  **)
  4119.                       (** LAST_SLOT refer to this slot and initialize **)
  4120.                       (** its fields. Add SOURCE_LINE to the new code **)
  4121.                       (** segment LAST_SLOT^.CODE.                    **)
  4122.                       NEW (LAST_STUB^.SLOTS);
  4123.                       LAST_SLOT := LAST_STUB^.SLOTS;
  4124.                       WITH LAST_SLOT^ DO
  4125.                       BEGIN
  4126.                           SP_INIT_STR (NAME);
  4127.                           ST_INIT_SEG (SRC_IMG);
  4128.                           STUB_REF := NIL;
  4129.                           ST_INIT_SEG (CODE);
  4130.                           NEXT_SLOT := NIL;
  4131.                           ST_PUT_SEG (SOURCE_LINE, CODE);
  4132.                       END (*WITH*);
  4133.                       (*********  END OF BUILD_CODE-STRUCT (18)  *******)
  4134.                   END (*IF.IF*);
  4135.               END
  4136.               ELSE IF SEGMENT_TYPE = SLOT THEN
  4137.               BEGIN
  4138.                   SEGMENT_TYPE := CODE;
  4139.                   (*************  BUILD_CODE_STRUCT (19)  **************)
  4140.                   (** Start of a new code segment immediately follo-  **)
  4141.                   (** wing a slot segment. Add SOURCE_LINE to the     **)
  4142.                   (** to the code segment LAST_SLOT^.CODE.            **)
  4143.                   WITH LAST_SLOT^ DO
  4144.                       ST_PUT_SEG (SOURCE_LINE, CODE);
  4145.                   (*********  End of BUILD_CODE_STRUCT (19)  ***********)
  4146.               END
  4147.               ELSE IF SEGMENT_TYPE = CODE THEN
  4148.               BEGIN
  4149.                   IF (CODE_STRUCT.LAST_STUB^.OPTIONS.QUICK) AND
  4150.                                 (FT_GET_LINE_LENGTH (SOURCE_LINE)=0) THEN
  4151.                   BEGIN
  4152.                       (*************  BUILD_CODE_STRUCT (20)  **********)
  4153.                       (** End of current stub block. Scan options     **)
  4154.                       (** from LAST_SLOT^.SRC_IMG and store them in   **)
  4155.                       (** LAST_SLOT^.OPTIONS.                         **)
  4156.                       SCAN_OPTIONS (LAST_SLOT^.OPTIONS, LAST_SLOT^.SRC_IMG,
  4157.                                     RUN_INFO,           SEGMENT_TYPE);
  4158.                       LINE_INFO.OPTIONS := FALSE;
  4159.                       (*********  End of BUILD_CODE_STRUCT (20)  *******)
  4160.  
  4161.                       END_OF_STUB_BLOCK := TRUE;
  4162.                   END
  4163.                   ELSE
  4164.                   BEGIN
  4165.                       (*************  BUILD_CODE_STRUCT (21)  **********)
  4166.                       (** Continuation of the code segment. Add       **)
  4167.                       (** SOURCE_LINE to segment LAST_SLOT^.CODE.     **)
  4168.                       WITH LAST_SLOT^ DO
  4169.                           ST_PUT_LINE (SOURCE_LINE, CODE);
  4170.                       (*********  End of BUILD_CODE_STRUCT (21)  *******)
  4171.                   END (*IF*);
  4172.               END (*IF.IF.IF*);
  4173.           END;
  4174.           END (*CASE.WITH*);
  4175.       END (*WHILE*);
  4176.  
  4177.       IF (NOT END_OF_STUB_BLOCK) THEN
  4178.       BEGIN
  4179.           IF (NOT CODE_STRUCT.LAST_STUB^.OPTIONS.QUICK) THEN
  4180.           BEGIN
  4181.               (*************  BUILD_CODE_STRUCT (22)  ******************)
  4182.               (** File exhausted but current stub block not closed by **)
  4183.               (** a line of category L2. Issue an error using         **)
  4184.               (** FILE_SPEC.                                          **)
  4185.               STRING132.LENGTH := 0;
  4186.               STRING132.BODY := EMPTY_STRING_FIXED;
  4187.               FT_INIT_LINE (SOURCE_LINE);
  4188.               DIAG (WARN, 'BUILD_C_S (22)           ', SOURCE_LINE,
  4189.                           CODE_STRUCT.LAST_STUB^.SRC_IMG, STRING132);
  4190.               (*************  End of BUILD_CODE_STRUCT (22)  ***********)
  4191.           END
  4192.           ELSE IF SEGMENT_TYPE = CODE THEN
  4193.           BEGIN
  4194.               (*************  BUILD_CODE_STRUCT (23)  ******************)
  4195.               (** The last quick stub in the file didn't end with an  **)
  4196.               (** L5-line, but with EOF. So the options from LAST_-   **)
  4197.               (** SLOT.SRC_IMG must be scanned and stored in LAST_-   **)
  4198.               (** SLOT.OPTIONS here.                                  **)
  4199.               SCAN_OPTIONS (LAST_SLOT^.OPTIONS, LAST_SLOT^.SRC_IMG,
  4200.                             RUN_INFO,           SEGMENT_TYPE);
  4201.               LINE_INFO.OPTIONS := FALSE;
  4202.               (*************  End of BUILD_CODE_STRUCT (23)  ***********)
  4203.           END (*IF*);
  4204.       END (*IF*);
  4205.       (*************  End of BUILD_CODE_STRUCT (body)  *****************)
  4206.  
  4207.   END (*PROCEDURE BUILD_CODE_STRUCT*);
  4208.  
  4209.  
  4210.   (*********************************************************************)
  4211.   (* Routine:     SCAN_FILES   - SCAN all source FILES.                *)
  4212.   (* Purpose:     To coordinate the scanning of all the sourcefiles on *)
  4213.   (*              file level. More detailed activities are delegated.  *)
  4214.   (* Interface:   RUN_INFO:       Structure containing all needed info *)
  4215.   (*                              for this CLIP run.                   *)
  4216.   (*              CODE_STRUCT:    Internal representation of stub-,    *)
  4217.   (*                              slot- and code-segments.             *)
  4218.   (*********************************************************************)
  4219.   PROCEDURE SCAN_FILES (VAR CODE_STRUCT: CODE_STRUCT_;
  4220.                             RUN_INFO:    RUN_INFO_);
  4221.  
  4222.   VAR
  4223.       SCAN_FILE_STOP: BOOLEAN;
  4224.       FILE_CNT:   INTEGER;
  4225.       I:          INTEGER;
  4226.       LINE_INFO:          LINE_INFO_ ;
  4227.       SOURCE_LINE:        LINE_DES_  ;
  4228.       DUMMY:              ERROR_CODE_;
  4229.       STRING132:  STRING132_;
  4230.       SEGMENT:    SEGMENT_DES_;
  4231.  
  4232.   BEGIN
  4233.       (*******                SCAN_FILES (body)                  *******)
  4234.       SCAN_FILE_STOP :=   FALSE;
  4235.  
  4236.       (*********************  SCAN_FILES (1)  **************************)
  4237.       (** Try to open all source files of which the names are kept by **)
  4238.       (** RUN_INFO. List inaccessible files. Set SCAN_FILE_STOP to    **)
  4239.       (** TRUE when at least one file gives a problem.                **)
  4240.       WITH RUN_INFO DO
  4241.       FOR FILE_CNT := 1 TO NR_SRC_FILES DO
  4242.       BEGIN
  4243.           IF FT_CHECK_FILE (SOURCE_FILES [FILE_CNT]) <> 0 THEN
  4244.           BEGIN
  4245.               WRITE ('ERROR checking source file:  ');
  4246.               FOR I := 1 TO SOURCE_FILES [FILE_CNT].LENGTH DO
  4247.                   WRITE (SOURCE_FILES [FILE_CNT].BODY [I]);
  4248.               WRITELN;
  4249.     
  4250.               IF REPORT_OK THEN
  4251.               BEGIN
  4252.                   WRITE (REPORT_FILE, 'ERROR checking source file:  ');
  4253.                   FOR I := 1 TO SOURCE_FILES [FILE_CNT].LENGTH DO
  4254.                       WRITE (REPORT_FILE, SOURCE_FILES [FILE_CNT].BODY [I]);
  4255.                   WRITELN (REPORT_FILE);
  4256.               END (*IF*);
  4257.     
  4258.               SCAN_FILE_STOP := TRUE;
  4259.           END (*IF*);
  4260.       END (*FOR.WITH*);
  4261.       (*****************  End of SCAN_FILES (1)  ***********************)
  4262.  
  4263.       IF NOT SCAN_FILE_STOP THEN
  4264.       BEGIN
  4265.           (*********************  SCAN_FILES (2)  **********************)
  4266.           (** Build CODE_STRUCT from the source files specified by    **)
  4267.           (** RUN_INFO.                                               **)
  4268.           FOR FILE_CNT := 1 TO RUN_INFO.NR_SRC_FILES DO
  4269.           BEGIN
  4270.               (* Open and reset file with given specification using    *)
  4271.               (* the function FT_INOPEN from the module FT.            *)
  4272.               IF FT_INOPEN (RUN_INFO.SOURCE_FILES [FILE_CNT]) <= 0 THEN
  4273.               BEGIN
  4274.                   WRITE ('Scanning file: ');
  4275.                   FOR I := 1 TO RUN_INFO.SOURCE_FILES [FILE_CNT].LENGTH DO
  4276.                       WRITE (RUN_INFO.SOURCE_FILES [FILE_CNT].BODY[I]);
  4277.                   WRITELN;
  4278.         
  4279.                   IF REPORT_OK THEN
  4280.                   BEGIN
  4281.                       WRITE (REPORT_FILE, 'Scanning file: ');
  4282.                       FOR I := 1 TO RUN_INFO.SOURCE_FILES [FILE_CNT].LENGTH DO
  4283.                           WRITE (REPORT_FILE,
  4284.                                        RUN_INFO.SOURCE_FILES [FILE_CNT].BODY[I]);
  4285.                       WRITELN (REPORT_FILE);
  4286.                   END (*IF*);
  4287.         
  4288.                   WHILE NOT FT_EOF DO
  4289.                   BEGIN
  4290.                       (* Read the next line from the source file and   *)
  4291.                       (* initialize LINE_INFO and the Buffer.          *)
  4292.                       FT_RDLN (SOURCE_LINE);
  4293.                       WITH LINE_INFO DO
  4294.                           OPTIONS := FALSE;
  4295.                       SP_INIT_BUFFER;
  4296.         
  4297.                       (* Determine the category this line belongs to.  *)
  4298.                       WITH RUN_INFO DO
  4299.                       BEGIN
  4300.                           IF SOURCE_LINE.USED >
  4301.                                       CLIP_LPAR.LENGTH + CLIP_RPAR.LENGTH THEN
  4302.                               SCAN_LINE (LINE_INFO, SOURCE_LINE, RUN_INFO)
  4303.                           ELSE
  4304.                               LINE_INFO.CATEGORY := L5;
  4305.                       END (*WITH*);
  4306.         
  4307.                       (* Proces this line according to its catagory.   *)
  4308.                       CASE LINE_INFO.CATEGORY OF
  4309.                       L1:
  4310.                           BEGIN
  4311.                           (*************  SCAN_FILES (2.1)  ********************)
  4312.                           (** Start of a new stub. Switch to active mode and  **)
  4313.                           (** build CODE_STRUCT from successive lines using   **)
  4314.                           (** RUN_INFO, SOURCE_LINE and LINE_INFO.            **)
  4315.                         
  4316.                           BUILD_CODE_STRUCT (CODE_STRUCT, RUN_INFO, SOURCE_LINE, LINE_INFO);
  4317.                         
  4318.                           (*************  End of SCAN_FILES (2.1)  *************)
  4319.                           END;
  4320.                       L2:
  4321.                           BEGIN
  4322.                           (*************  SCAN_FILES (2.2)  ********************)
  4323.                           (** Illegal in passive mode. Generate an error from **)
  4324.                           (** the information in SOURCE_LINE.                 **)
  4325.                           ST_INIT_SEG (SEGMENT);
  4326.                           STRING132.BODY := EMPTY_STRING_FIXED;
  4327.                           STRING132.LENGTH := 0;
  4328.                           DIAG (WARN, 'SCAN_FILES (2.2)         ', SOURCE_LINE, SEGMENT, STRING132);
  4329.                           (*************  End of SCAN_FILES (2.2)  *************)
  4330.                           END;
  4331.                       L3:
  4332.                           BEGIN
  4333.                           (*************  SCAN_FILES (2.3)  ********************)
  4334.                           (** Illegal in passive mode. Generate an error from **)
  4335.                           (** the information in SOURCE_LINE.                 **)
  4336.                           ST_INIT_SEG (SEGMENT);
  4337.                           STRING132.LENGTH := 0;
  4338.                           STRING132.BODY := EMPTY_STRING_FIXED;
  4339.                           DIAG (ERR, 'SCAN_FILES (2.3)         ', SOURCE_LINE, SEGMENT, STRING132);
  4340.                           (*************  End of SCAN_FILES (2.3)  *************)
  4341.                           END;
  4342.                       L4,
  4343.                       L5:
  4344.                           BEGIN
  4345.                           (* Nothing to be done. Flush this line.              *)
  4346.                           END;
  4347.                       END (*CASE*);
  4348.                   END (*WHILE*);
  4349.                   DUMMY := FT_INCLOSE;
  4350.               END
  4351.               ELSE
  4352.               BEGIN
  4353.                   (*********************  SCAN_FILES (2.4)  ********************)
  4354.                   (** Access problem with this source file. Issue error using **)
  4355.                   (** its specification in RUN_INFO.                          **)
  4356.                   WITH RUN_INFO DO
  4357.                   BEGIN
  4358.                       WRITE ('ERROR opening source file:  ');
  4359.                       FOR I := 1 TO SOURCE_FILES [FILE_CNT].LENGTH DO
  4360.                           WRITE (SOURCE_FILES [FILE_CNT].BODY [I]);
  4361.                       WRITELN;
  4362.                 
  4363.                       IF REPORT_OK THEN
  4364.                       BEGIN
  4365.                           WRITE (REPORT_FILE, 'ERROR opening source file:  ');
  4366.                           FOR I := 1 TO SOURCE_FILES [FILE_CNT].LENGTH DO
  4367.                               WRITE (REPORT_FILE, SOURCE_FILES [FILE_CNT].BODY [I]);
  4368.                           WRITELN (REPORT_FILE);
  4369.                       END (*IF*);
  4370.                   END (*WITH*);
  4371.                   (*****************  End of SCAN_FILES (2.4)  *****************)
  4372.               END (*IF*);
  4373.           END (*FOR*);
  4374.           (*****************  End of SCAN_FILES (2)  *******************)
  4375.       END (*IF*);
  4376.       (*****************  End of SCAN_FILES (body)  ********************)
  4377.   END (*PROCEDURE SCAN_FILES*);
  4378.  
  4379.  
  4380.   (*********************************************************************)
  4381.   (* Routine:    CHECK_CIRC  - CHECK FOR CIRCularity.                  *)
  4382.   (* Purpose:    To check possible circularity of CODE_STRUCT.         *)
  4383.   (* Interface:  CODE_STRUCT -   Structure to be examined.             *)
  4384.   (*             LIST_HEAD -     First element of shadow list.         *)
  4385.   (*********************************************************************)
  4386.   PROCEDURE CHECK_CIRC (VAR CODE_STRUCT: CODE_STRUCT_;
  4387.                         LIST_HEAD:   SHADOW_PTR_);
  4388.  
  4389.   VAR
  4390.       MAIN_STUB:      STB_PTR_;
  4391.       SHADOW_STUB:    SHADOW_PTR_;
  4392.       STUB:           STB_PTR_;
  4393.       CIRCULARITY,
  4394.       REMOVED:        BOOLEAN;
  4395.  
  4396.   (*******                CHECK_CIRC routines                    *******)
  4397.  
  4398.   (*********************************************************************)
  4399.   (* Routine:     LOCATE_CIRC -   LOCATE CIRCularity.                  *)
  4400.   (* Purpose:     Locate and remove circularity in CODE_STRUCT.        *)
  4401.   (* Interface:   CODE_STRUCT -   The structure to be checked.         *)
  4402.   (*              STUB -          The stub currently checked.          *)
  4403.   (*              CIRCULARITY -   Flags if circularity is detected.    *)
  4404.   (*              REMOVED -       Flags if circularity is removed.     *)
  4405.   (*********************************************************************)
  4406.   PROCEDURE LOCATE_CIRC (VAR CODE_STRUCT: CODE_STRUCT_;
  4407.                          VAR STUB:        STB_PTR_;
  4408.                          VAR CIRCULARITY: BOOLEAN;
  4409.                          VAR REMOVED:     BOOLEAN);
  4410.  
  4411.   (*******        LOCATE_CIRC labels (#Quick)                    *******)
  4412.   LABEL
  4413.       MYEXIT;
  4414.  
  4415.   VAR
  4416.       SLOT:       SLT_PTR_;
  4417.       HELP_STUB:  STB_PTR_;
  4418.       TWIN_STUB:  STB_PTR_;
  4419.  
  4420.   (*******    LOCATE_CIRC routines                               *******)
  4421.  
  4422.   (*********************************************************************)
  4423.   (* Routine:     TRACEBACK                                            *)
  4424.   (* Purpose:     -In case of an unremoved circularity: Remove circu-  *)
  4425.   (*              larity and show the responsible slot.                *)
  4426.   (*              -Show a stub of the circularity-chain.               *)
  4427.   (* Interface:   STUB -    The stub, which was being checked.         *)
  4428.   (*              SLOT -    The slot, at which STUB is pointing.       *)
  4429.   (*              REMOVED - Flags if the circularity is removed.       *)
  4430.   (*********************************************************************)
  4431.   PROCEDURE TRACEBACK (    STUB:    STB_PTR_;
  4432.                            SLOT:    SLT_PTR_;
  4433.                        VAR REMOVED: BOOLEAN);
  4434.   BEGIN
  4435.       IF NOT REMOVED THEN
  4436.       BEGIN
  4437.           SLOT^.STUB_REF := NIL;
  4438.           REMOVED := TRUE;
  4439.           WRITELN('Circularity detected !!! TRACE BACK:');
  4440.           WRITELN ('slot:');
  4441.           ST_WRITE_SEG (SLOT^.SRC_IMG, 0, 0);
  4442.           WRITELN;
  4443.  
  4444.           IF REPORT_OK THEN
  4445.           BEGIN
  4446.               WRITELN (REPORT_FILE,
  4447.                                  'Circularity detected !!! TRACE BACK:');
  4448.               WRITELN (REPORT_FILE, 'slot:');
  4449.               ST_WRITE_SEG (SLOT^.SRC_IMG, 0, 3);
  4450.               WRITELN (REPORT_FILE);
  4451.           END (*IF*);
  4452.  
  4453.       END(*IF*);
  4454.       IF NOT SP_IS_EMPTY_STR (STUB^.OPTIONS.FILE_NAME) THEN
  4455.       BEGIN
  4456.           WRITELN ('Main stub:');
  4457.           ST_WRITE_SEG (STUB^.SRC_IMG, 0, 0);
  4458.           WRITELN ('------------------------------------',
  4459.                    '------------------------------------');
  4460.  
  4461.           IF REPORT_OK THEN
  4462.           BEGIN
  4463.               WRITELN (REPORT_FILE, 'Main stub:');
  4464.               ST_WRITE_SEG (STUB^.SRC_IMG, 0, 3);
  4465.               WRITELN (REPORT_FILE,
  4466.                        '------------------------------------',
  4467.                        '------------------------------------');
  4468.           END (*IF*);
  4469.       END
  4470.       ELSE
  4471.       BEGIN
  4472.           WRITELN ('Stub:');
  4473.           ST_WRITE_SEG (STUB^.SRC_IMG, 0, 0);
  4474.  
  4475.           IF REPORT_OK THEN
  4476.           BEGIN
  4477.               WRITELN (REPORT_FILE, 'Stub:');
  4478.               ST_WRITE_SEG (STUB^.SRC_IMG, 0, 3);
  4479.           END (*IF*);
  4480.       END (*IF*);
  4481.       WRITELN;
  4482.    END (*TRACEBACK*);
  4483.   (*********************  End of LOCATE_CIRC routines  *****************)
  4484.  
  4485.   BEGIN
  4486.       (*******                LOCATE_CIRC (body)                 *******)
  4487.       WITH STUB^ DO
  4488.       BEGIN
  4489.           CIRCULARITY := STUB^.VISITED;
  4490.           IF NOT CIRCULARITY THEN
  4491.           BEGIN
  4492.               STUB^.VISITED := TRUE;
  4493.               SLOT := STUB^.SLOTS;
  4494.     
  4495.               (*********************  LOCATE_CIRC (1)  *********************)
  4496.               (** Check if the SLOTs of STUB are pointing at any stubs.   **)
  4497.               (** If so, locate circularities in these stubs and their    **)
  4498.               (** structure behind. Leave this level of the procedure     **)
  4499.               (** through MYEXIT in case of circularity.                  **)
  4500.               WHILE SLOT <> NIL DO
  4501.               BEGIN
  4502.                   IF SLOT^.STUB_REF <> NIL THEN
  4503.                   BEGIN
  4504.                       LOCATE_CIRC(CODE_STRUCT,SLOT^.STUB_REF,
  4505.                                               CIRCULARITY,REMOVED);
  4506.                       IF CIRCULARITY THEN
  4507.                       BEGIN
  4508.                           (*****************  LOCATE_CIRC (1.1)  *******************)
  4509.                           (** Remove the link causing the circularity in CODE_-   **)
  4510.                           (** STRUCT, if not removed already. Mention STUB in the **)
  4511.                           (** traceback. If this STUB is a main stub, set CIRCU-  **)
  4512.                           (** RITY, REMOVED and VISITED of all next stubs back to **)
  4513.                           (** FALSE and locate circularities in this new CODE_-   **)
  4514.                           (** STRUCT. Leave this level of the procedure through   **)
  4515.                           (** MYEXIT.                                             **)
  4516.                           TRACEBACK (STUB, SLOT, REMOVED);
  4517.                           IF NOT SP_IS_EMPTY_STR (STUB^.OPTIONS.FILE_NAME) THEN
  4518.                           BEGIN
  4519.                               CIRCULARITY := FALSE;
  4520.                               REMOVED := FALSE;
  4521.                               HELP_STUB := STUB;
  4522.                               WHILE HELP_STUB <> NIL DO
  4523.                               BEGIN
  4524.                                   HELP_STUB^.VISITED := FALSE;
  4525.                                   HELP_STUB := HELP_STUB^.NEXT_STUB;
  4526.                               END (*WHILE*);
  4527.                               LOCATE_CIRC (CODE_STRUCT, STUB, CIRCULARITY, REMOVED);
  4528.                           END(*IF*);
  4529.                           GOTO MYEXIT;
  4530.                           (*************  End of LOCATE_CIRC (1.1)  ****************)
  4531.                       END (*IF*);
  4532.             
  4533.                       (*****************  LOCATE_CIRC (1.2)  ***********************)
  4534.                       (** Check if SLOT^.STUB_REF is pointing at any twin stubs.  **)
  4535.                       (** If so, locate circularities in these stubs. In case of  **)
  4536.                       (** circularity, remove the responsible link, if not        **)
  4537.                       (** removed already, mention STUB in the traceback and      **)
  4538.                       (** leave this level of the procedure through MYEXIT.       **)
  4539.                       TWIN_STUB := SLOT^.STUB_REF^.NEXT_TWIN;
  4540.                       WHILE TWIN_STUB <> NIL DO
  4541.                       BEGIN
  4542.                           LOCATE_CIRC (CODE_STRUCT, TWIN_STUB, CIRCULARITY, REMOVED);
  4543.                           IF CIRCULARITY THEN
  4544.                           BEGIN
  4545.                               TRACEBACK (STUB, SLOT, REMOVED);
  4546.                               GOTO MYEXIT;
  4547.                           END (*IF*);
  4548.                           TWIN_STUB := TWIN_STUB^.NEXT_TWIN;
  4549.                       END (*WHILE*);
  4550.                       (*************  End of LOCATE_CIRC (1.2)  ********************)
  4551.             
  4552.                       SLOT^.STUB_REF^.VISITED := FALSE;
  4553.                   END (*IF*);
  4554.                   SLOT := SLOT^.NEXT_SLOT;
  4555.               END (*WHILE*);
  4556.               (*****************  End of LOCATE_CIRC (1)  ******************)
  4557.     
  4558.               STUB^.VISITED := FALSE;
  4559.           END (*IF*);
  4560.       END (*WITH*);
  4561.       MYEXIT:
  4562.       (*****************  End of LOCATE_CIRC (body)  *******************)
  4563.   END (*PROCEDURE LOCATE_CIRC*);
  4564.   (*****************  End of procedure LOCATE_CIRC  ********************)
  4565.  
  4566.   BEGIN
  4567.       SHADOW_STUB := LIST_HEAD;
  4568.       WHILE SHADOW_STUB <> NIL DO
  4569.       BEGIN
  4570.           MAIN_STUB := NIL;
  4571.     
  4572.           WITH SHADOW_STUB^.STUB_POINTER^ DO
  4573.           BEGIN
  4574.               IF NOT SP_IS_EMPTY_STR (OPTIONS.FILE_NAME) THEN
  4575.                   MAIN_STUB := SHADOW_STUB^.STUB_POINTER;
  4576.           END (*WITH*);
  4577.     
  4578.           IF MAIN_STUB <> NIL THEN
  4579.           BEGIN
  4580.               STUB := CODE_STRUCT.FIRST_STUB;
  4581.               WHILE STUB <> NIL DO
  4582.               BEGIN
  4583.                       STUB^.VISITED := FALSE;
  4584.                       STUB := STUB^.NEXT_STUB;
  4585.               END (*WHILE*);
  4586.     
  4587.               CIRCULARITY :=  FALSE;
  4588.               REMOVED :=      FALSE;
  4589.               LOCATE_CIRC (CODE_STRUCT, MAIN_STUB, CIRCULARITY, REMOVED);
  4590.           END (*IF*);
  4591.           SHADOW_STUB := SHADOW_STUB^.NEXT;
  4592.       END (*WHILE*)
  4593.   END (*PROCEDURE CHECK_CIRC*);
  4594.  
  4595.  
  4596.   (*********************************************************************)
  4597.   (* Routine:     ORDER_TWINS -   ORDER TWIN stub chains.              *)
  4598.   (* Purpose:     To (re)order the chains of twin stubs.               *)
  4599.   (* Interface:   SHADOW_LIST:    The list of pointers to the first    *)
  4600.   (*                              elements of the twin stub chain.     *)
  4601.   (*              CODE_STRUCT:    Structure of stubs and slots.        *)
  4602.   (*              LIST_HEAD:      Pointer to first element of the      *)
  4603.   (*                              shadow_list.                         *)
  4604.   (*********************************************************************)
  4605.   PROCEDURE ORDER_TWINS (VAR SHADOW_LIST:    SHADOW_LIST_;
  4606.                          VAR CODE_STRUCT:    CODE_STRUCT_;
  4607.                          VAR LIST_HEAD:      SHADOW_PTR_);
  4608.  
  4609.   VAR
  4610.       FIRST_TWIN:         STB_PTR_;
  4611.       SHADOW_STUB:        SHADOW_PTR_;
  4612.       PREV_SHADOW_STUB:   SHADOW_PTR_;
  4613.       TWIN_STUB:          STB_PTR_;
  4614.       PREV_TWIN:          STB_PTR_;
  4615.       CONTINUE:           BOOLEAN;
  4616.   LAST_TWIN:          STB_PTR_;
  4617.   SEPARATOR_STUB:     STB_PTR_;
  4618.   STUB_WALKER:        STB_PTR_;
  4619.   HELP_STUB:          STB_PTR_;
  4620.       ERROR:          BOOLEAN;
  4621.       DUMMY_LINE:     LINE_DES_;
  4622.       STRING132:      STRING132_;
  4623.  
  4624.   BEGIN
  4625.       (*********************  ORDER_TWINS body  ************************)
  4626.       PREV_SHADOW_STUB :=  NIL;
  4627.       SHADOW_STUB :=       LIST_HEAD;
  4628.       WHILE SHADOW_STUB <> NIL DO
  4629.       BEGIN
  4630.            FIRST_TWIN := SHADOW_STUB^.STUB_POINTER;
  4631.     
  4632.            (************************  ORDER_TWINS (1)  *********************)
  4633.            (** Order the twin stub chain headed by FIRST_TWIN. Make sure  **)
  4634.            (** that its first element remains accessible through by       **)
  4635.            (** SHADOW_STUB.                                               **)
  4636.            PREV_TWIN := NIL;
  4637.            TWIN_STUB := FIRST_TWIN;
  4638.            WHILE TWIN_STUB <> NIL DO
  4639.            BEGIN
  4640.                IF TWIN_STUB^.OPTIONS.DEFAULT THEN
  4641.                BEGIN
  4642.                    (*********************  ORDER_TWINS (1.1)  *******************)
  4643.                    (** Remove the TWIN_STUB from the list if it is no longer   **)
  4644.                    (** needed. Update SHADOW_LIST if needed.                   **)
  4645.                    IF (TWIN_STUB^.NEXT_TWIN <> NIL) AND
  4646.                        (PREV_TWIN = NIL)
  4647.                    THEN SHADOW_STUB^.STUB_POINTER := TWIN_STUB^.NEXT_TWIN
  4648.                    ELSE IF (TWIN_STUB^.NEXT_TWIN <> NIL) AND
  4649.                             (PREV_TWIN <> NIL)
  4650.                    THEN PREV_TWIN^.NEXT_TWIN := TWIN_STUB^.NEXT_TWIN
  4651.                    ELSE IF (TWIN_STUB^.NEXT_TWIN = NIL) AND
  4652.                            (PREV_TWIN <> NIL)
  4653.                    THEN PREV_TWIN^.NEXT_TWIN := NIL
  4654.                    ELSE
  4655.                    BEGIN
  4656.                        (* Nothing remains to be done here.              *)
  4657.                    END(*IF.IF.IF*);
  4658.                    (*****************  End of ORDER_TWINS (1.1)  ****************)
  4659.                END (*IF*);
  4660.                IF TWIN_STUB^.OPTIONS.LEADER THEN
  4661.                BEGIN
  4662.                    (*********************  ORDER_TWINS (1.2)  *******************)
  4663.                    (** Remove TWIN_STUB and put it ahead of the twin stub      **)
  4664.                    (** chain. Remove SHADOW_STUB from SHADOW_LIST if TWIN_STUB **)
  4665.                    (** is no longer needed.                                    **)
  4666.                    IF (TWIN_STUB^.NEXT_TWIN = NIL) AND (PREV_TWIN = NIL) THEN
  4667.                    BEGIN
  4668.                        IF PREV_SHADOW_STUB = NIL THEN
  4669.                        BEGIN
  4670.                            LIST_HEAD := SHADOW_STUB^.NEXT;
  4671.                            SHADOW_STUB := LIST_HEAD;
  4672.                            PREV_SHADOW_STUB := NIL;
  4673.                        END
  4674.                        ELSE
  4675.                        BEGIN
  4676.                            PREV_SHADOW_STUB^.NEXT := SHADOW_STUB^.NEXT;
  4677.                            SHADOW_STUB := PREV_SHADOW_STUB;
  4678.                        END (*IF*);
  4679.                    END
  4680.                    ELSE IF (TWIN_STUB^.NEXT_TWIN <> NIL) AND (PREV_TWIN <> NIL) THEN
  4681.                    BEGIN
  4682.                        PREV_TWIN^.NEXT_TWIN := TWIN_STUB^.NEXT_TWIN;
  4683.                        TWIN_STUB^.NEXT_TWIN := FIRST_TWIN;
  4684.                        SHADOW_STUB^.STUB_POINTER := TWIN_STUB;
  4685.                        TWIN_STUB := PREV_TWIN;
  4686.                        FIRST_TWIN := SHADOW_STUB^.STUB_POINTER;
  4687.                    END
  4688.                    ELSE IF (TWIN_STUB^.NEXT_TWIN = NIL) AND (PREV_TWIN <> NIL) THEN
  4689.                    BEGIN
  4690.                        PREV_TWIN^.NEXT_TWIN := NIL;
  4691.                        TWIN_STUB^.NEXT_TWIN := FIRST_TWIN;
  4692.                        SHADOW_STUB^.STUB_POINTER := TWIN_STUB;
  4693.                        TWIN_STUB := PREV_TWIN;
  4694.                        FIRST_TWIN := SHADOW_STUB^.STUB_POINTER;
  4695.                    END
  4696.                    ELSE
  4697.                    BEGIN
  4698.                       (* Leader stub is in place,nothing remains to be  *)
  4699.                       (* done here.                                     *)
  4700.                    END (*IF.IF.IF*);
  4701.                    (*****************  End of ORDER_TWINS (1.2)  ****************)
  4702.                END (*IF*);
  4703.                IF TWIN_STUB^.OPTIONS.TRAILER THEN
  4704.                BEGIN
  4705.                    (*********************  ORDER_TWINS (1.3)  *******************)
  4706.                    (** Remove TWIN_STUB and put it at the tail of the twin     **)
  4707.                    (** stub chain.                                             **)
  4708.                  
  4709.                    (* Locate the last stub in the twin stub chain       *)
  4710.                    LAST_TWIN := TWIN_STUB;
  4711.                    WHILE LAST_TWIN^.NEXT_TWIN <> NIL DO
  4712.                        LAST_TWIN := LAST_TWIN^.NEXT_TWIN;
  4713.                    IF (TWIN_STUB^.NEXT_TWIN = NIL) AND (PREV_TWIN = NIL) THEN
  4714.                    BEGIN
  4715.                        IF PREV_SHADOW_STUB = NIL THEN
  4716.                        BEGIN
  4717.                            LIST_HEAD := SHADOW_STUB^.NEXT;
  4718.                            SHADOW_STUB := LIST_HEAD;
  4719.                            PREV_SHADOW_STUB := NIL;
  4720.                        END
  4721.                        ELSE
  4722.                        BEGIN
  4723.                            PREV_SHADOW_STUB^.NEXT := SHADOW_STUB^.NEXT;
  4724.                            SHADOW_STUB := PREV_SHADOW_STUB;
  4725.                        END (*IF*);
  4726.                    END
  4727.                    ELSE IF (TWIN_STUB^.NEXT_TWIN <> NIL) AND (PREV_TWIN <> NIL) THEN
  4728.                    BEGIN
  4729.                        PREV_TWIN^.NEXT_TWIN := TWIN_STUB^.NEXT_TWIN;
  4730.                        LAST_TWIN^.NEXT_TWIN := TWIN_STUB;
  4731.                        LAST_TWIN := LAST_TWIN^.NEXT_TWIN;
  4732.                        LAST_TWIN^.NEXT_TWIN := NIL;
  4733.                        TWIN_STUB := PREV_TWIN;
  4734.                    END
  4735.                    ELSE IF (TWIN_STUB^.NEXT_TWIN <> NIL) AND (PREV_TWIN = NIL) THEN
  4736.                    BEGIN
  4737.                        SHADOW_STUB^.STUB_POINTER := TWIN_STUB^.NEXT_TWIN;
  4738.                        LAST_TWIN^.NEXT_TWIN := TWIN_STUB;
  4739.                        LAST_TWIN := LAST_TWIN^.NEXT_TWIN;
  4740.                        LAST_TWIN^.NEXT_TWIN := NIL;
  4741.                        FIRST_TWIN := SHADOW_STUB^.STUB_POINTER;
  4742.                        TWIN_STUB := FIRST_TWIN;
  4743.                        PREV_TWIN := NIL;
  4744.                    END
  4745.                    ELSE
  4746.                    BEGIN
  4747.                        (* Trailer stub is in position. Nothing remains  *)
  4748.                        (* to be done.                                   *)
  4749.                    END (*IF.IF.IF*);
  4750.                    (*****************  End of ORDER_TWINS (1.3)  ****************)
  4751.                END (*IF*);
  4752.                PREV_TWIN := TWIN_STUB;
  4753.                TWIN_STUB := TWIN_STUB^.NEXT_TWIN;
  4754.            END (*WHILE*);
  4755.            TWIN_STUB := FIRST_TWIN;
  4756.            PREV_TWIN := NIL;
  4757.            CONTINUE :=  TRUE;
  4758.            WHILE (TWIN_STUB^.NEXT_TWIN <> NIL) AND (CONTINUE) DO
  4759.            BEGIN
  4760.                IF TWIN_STUB^.OPTIONS.SEPARATOR THEN
  4761.                BEGIN
  4762.                    (*********************  ORDER_TWINS (1.4)  *******************)
  4763.                    (** Copy the seperator TWIN_STUB in between all other stubs **)
  4764.                    (** of the twin stub chain.                                 **)
  4765.                    IF PREV_TWIN = NIL THEN
  4766.                    BEGIN
  4767.                        FIRST_TWIN := TWIN_STUB^.NEXT_TWIN;
  4768.                        SHADOW_STUB^.STUB_POINTER := FIRST_TWIN;
  4769.                        SEPARATOR_STUB := TWIN_STUB;
  4770.                    END
  4771.                    ELSE
  4772.                    BEGIN
  4773.                        PREV_TWIN^.NEXT_TWIN := TWIN_STUB^.NEXT_TWIN;
  4774.                        SEPARATOR_STUB := TWIN_STUB;
  4775.                        TWIN_STUB := PREV_TWIN;
  4776.                    END (*IF*);
  4777.                    STUB_WALKER := FIRST_TWIN;
  4778.                    WHILE STUB_WALKER^.NEXT_TWIN <> NIL DO
  4779.                    BEGIN
  4780.                        HELP_STUB := STUB_WALKER^.NEXT_TWIN;
  4781.                        NEW (STUB_WALKER^.NEXT_TWIN);
  4782.                        STUB_WALKER :=  STUB_WALKER^.NEXT_TWIN;
  4783.                        STUB_WALKER^ := SEPARATOR_STUB^;
  4784.                        STUB_WALKER^.NEXT_TWIN := HELP_STUB;
  4785.                        STUB_WALKER :=  HELP_STUB;
  4786.                    END (*WHILE*);
  4787.                    (*****************  End of ORDER_TWINS (1.4)  ****************)
  4788.          
  4789.                     CONTINUE := FALSE;
  4790.                END (*IF*);
  4791.                PREV_TWIN := TWIN_STUB;
  4792.                TWIN_STUB := TWIN_STUB^.NEXT_TWIN;
  4793.            END (*WHILE*);
  4794.          
  4795.            (*************************  ORDER_TWINS (1.5)  ***********************)
  4796.            (** Examine the twin stub chain accessible by FIRST_TWIN. Generate  **)
  4797.            (** a diagnostic message in case the chain contains only LEADER,    **)
  4798.            (** SEPARATOR and TRAILER stubs.                                    **)
  4799.            ERROR := TRUE;
  4800.            STUB_WALKER := FIRST_TWIN;
  4801.            WHILE (STUB_WALKER <> NIL) AND (ERROR = TRUE) DO
  4802.            BEGIN
  4803.                IF (NOT STUB_WALKER^.OPTIONS.LEADER)    AND
  4804.                   (NOT STUB_WALKER^.OPTIONS.SEPARATOR) AND
  4805.                   (NOT STUB_WALKER^.OPTIONS.TRAILER)   THEN
  4806.                    ERROR := FALSE;
  4807.                STUB_WALKER := STUB_WALKER^.NEXT_TWIN;
  4808.            END (*WHILE*);
  4809.            IF (STUB_WALKER = NIL) AND (ERROR) THEN
  4810.            BEGIN
  4811.                STRING132.LENGTH := 0;
  4812.                STRING132.BODY := EMPTY_STRING_FIXED;
  4813.                FT_INIT_LINE (DUMMY_LINE);
  4814.                DIAG(WARN, 'ORDER_TWINS (1.5)        ', DUMMY_LINE,
  4815.                                        FIRST_TWIN^.SRC_IMG, STRING132);
  4816.                IF PREV_SHADOW_STUB = NIL THEN
  4817.                BEGIN
  4818.                    LIST_HEAD := SHADOW_STUB^.NEXT;
  4819.                    SHADOW_STUB := LIST_HEAD;
  4820.                    PREV_SHADOW_STUB := NIL;
  4821.                END
  4822.                ELSE
  4823.                BEGIN
  4824.                    PREV_SHADOW_STUB^.NEXT := SHADOW_STUB^.NEXT;
  4825.                    SHADOW_STUB := PREV_SHADOW_STUB;
  4826.                END (*IF*);
  4827.            END
  4828.            ELSE
  4829.            BEGIN
  4830.                (* The twin stub chain is ok and nothing remains to be   *)
  4831.                (* done here.                                            *)
  4832.            END (*IF*);
  4833.            (*********************  End of ORDER_TWINS (1.5)  ********************)
  4834.          
  4835.            (*********************  End of ORDER_TWINS (1)  ******************)
  4836.     
  4837.            PREV_SHADOW_STUB := SHADOW_STUB;
  4838.            SHADOW_STUB :=      SHADOW_STUB^.NEXT;
  4839.       END (*WHILE*);
  4840.       (*****************  End of ORDER_TWINS (body)  *******************)
  4841.   END (*PROCEDURE ORDER_TWINS*);
  4842.  
  4843.  
  4844.   (*********************************************************************)
  4845.   (* Routine:     ANALYSE - ANALYSEr phase                             *)
  4846.   (* Purpose:     To analyse the structure of stubs and slots.         *)
  4847.   (* Interface:   Input:  CODE_STRUCT  - the structure to be analyzed. *)
  4848.   (*              Output: CODE_STRUCT  - the analyzed structure.       *)
  4849.   (*********************************************************************)
  4850.   PROCEDURE ANALYSE (VAR CODE_STRUCT: CODE_STRUCT_);
  4851.  
  4852.   VAR
  4853.       SHADOW_LIST:    SHADOW_LIST_;
  4854.       LIST_HEAD:      SHADOW_PTR_;
  4855.       STRING132:      STRING132_;
  4856.       LAST_SHADOW:        SHADOW_PTR_;
  4857.       STUB:               STB_PTR_;
  4858.       LOCATED:            BOOLEAN;
  4859.       SHADOW_STUB:        SHADOW_PTR_;
  4860.   CANDIDATE_TWIN:     STB_PTR_;
  4861.       SLOT:               SLT_PTR_;
  4862.   STUB_REF:           STB_PTR_;
  4863.   DUMMY_LINE:         LINE_DES_;
  4864.  
  4865.   BEGIN
  4866.       (*********************  ANALYSE body  ****************************)
  4867.  
  4868.       LIST_HEAD := NIL;
  4869.  
  4870.       (*************************  ANALYSE (1)  *************************)
  4871.       (** Build SHADOW_LIST from the stub chain of CODE_STRUCT. Make  **)
  4872.       (** first element of SHADOW_LIST accessible by LIST_HEAD        **)
  4873.       STUB := CODE_STRUCT.FIRST_STUB;
  4874.       IF STUB <> NIL THEN
  4875.       BEGIN
  4876.           NEW (LIST_HEAD);
  4877.           LAST_SHADOW :=                  LIST_HEAD;
  4878.           LAST_SHADOW^.NEXT :=            NIL;
  4879.           LAST_SHADOW^.STUB_POINTER :=    STUB;
  4880.           STUB :=                         STUB^.NEXT_STUB;
  4881.           WHILE STUB <> NIL DO
  4882.           BEGIN
  4883.               (*********************  ANALYSE (1.1)  ***********************)
  4884.               (** Check if STUB^.NAME is already linked in SHADOW_LIST.   **)
  4885.               (** If not, make a new entry for this stub in SHADOW_LIST   **)
  4886.               (** and update LAST_SHADOW.                                 **)
  4887.               IF SP_IS_EMPTY_STR (STUB^.NAME) THEN
  4888.                   LOCATED := FALSE
  4889.               ELSE
  4890.               BEGIN
  4891.                   SHADOW_STUB := LIST_HEAD;
  4892.                   LOCATED := FALSE;
  4893.                   WHILE (NOT LOCATED) AND (SHADOW_STUB <> NIL) DO
  4894.                   BEGIN
  4895.                       IF SP_EQ (SHADOW_STUB^.STUB_POINTER^.NAME, STUB^.NAME) THEN
  4896.                           LOCATED := TRUE;
  4897.                       SHADOW_STUB := SHADOW_STUB^.NEXT;
  4898.                   END (*WHILE*);
  4899.               END (*IF*);
  4900.               IF NOT LOCATED THEN
  4901.               BEGIN
  4902.                   NEW (LAST_SHADOW^.NEXT);
  4903.                   LAST_SHADOW :=                  LAST_SHADOW^.NEXT;
  4904.                   LAST_SHADOW^.STUB_POINTER :=    STUB;
  4905.                   LAST_SHADOW^.NEXT :=            NIL;
  4906.               END (*IF*);
  4907.               (*****************  End of ANALYSE (1.1)  ********************)
  4908.     
  4909.               STUB := STUB^.NEXT_STUB;
  4910.           END (*WHILE*);
  4911.       END (*IF*);
  4912.       (*************************  End of ANALYSE (1)  **********************)
  4913.  
  4914.       IF LIST_HEAD <> NIL THEN
  4915.       BEGIN
  4916.           (************************  ANALYSE (2)  **********************)
  4917.           (** Link stubs with identical names into a twin stub chain  **)
  4918.           (** using NEXT_TWIN of the stub descriptor. Start each twin **)
  4919.           (** stub chain with the stub accessible by SHADOW_LIST.     **)
  4920.           SHADOW_STUB := LIST_HEAD;
  4921.           WHILE SHADOW_STUB <> NIL DO
  4922.           BEGIN
  4923.               STUB := SHADOW_STUB^.STUB_POINTER;
  4924.               IF NOT SP_IS_EMPTY_STR(STUB^.NAME) THEN
  4925.               WHILE STUB <> NIL DO
  4926.               BEGIN
  4927.                   (*****************  ANALYSE (2.1)  *******************)
  4928.                   (** Read through the list of stubs starting with    **)
  4929.                   (** STUB and set STUB^.NEXT_TWIN if a stub with     **)
  4930.                   (** the same name as STUB^.NAME found. Let          **)
  4931.                   (** CANDIDATE_TWIN refer to this stub.              **)
  4932.                   LOCATED := FALSE;
  4933.                   CANDIDATE_TWIN := STUB^.NEXT_STUB;
  4934.                   WHILE (CANDIDATE_TWIN <> NIL) AND (NOT LOCATED)  DO
  4935.                   BEGIN
  4936.                       IF SP_EQ (STUB^.NAME, CANDIDATE_TWIN^.NAME) THEN
  4937.                       BEGIN
  4938.                           LOCATED := TRUE;
  4939.                           STUB^.NEXT_TWIN := CANDIDATE_TWIN;
  4940.                       END
  4941.                       ELSE
  4942.                           CANDIDATE_TWIN := CANDIDATE_TWIN^.NEXT_STUB;
  4943.                   END (*WHILE*);
  4944.                   (*************  End of ANALYSE (2.1)  ****************)
  4945.         
  4946.                   STUB := CANDIDATE_TWIN;
  4947.               END (*WHILE*);
  4948.               SHADOW_STUB := SHADOW_STUB^.NEXT;
  4949.           END (*WHILE*);
  4950.           (*********************  End of ANALYSE (2)  ******************)
  4951.  
  4952.           (*********************  ANALYSE (3)  *************************)
  4953.           (** Reorder the twin stub chain by using the options of     **)
  4954.           (** the stub. SHADOW_LIST.STUB_POINTER must always refer to **)
  4955.           (** the first stub of the twin stub chain.                  **)
  4956.         
  4957.           ORDER_TWINS (SHADOW_LIST, CODE_STRUCT, LIST_HEAD);
  4958.         
  4959.           (*****************  End of ANALYSE (3)  **********************)
  4960.  
  4961.           (*********************  ANALYSE (4)  *************************)
  4962.           (** Update the field STUB_REF of the slots in the structure **)
  4963.           (** by searching a stub with the same name as the slot in   **)
  4964.           (** the structure. Use SHADOW_LIST to access the stubs.     **)
  4965.           (** Check if the option SLOT^.OPTIONS.MULTIPLE is used      **)
  4966.           (** correctly. Use SLOT^.SRC_IMG for diagnostics.           **)
  4967.           STUB := CODE_STRUCT.FIRST_STUB;
  4968.           WHILE STUB <> NIL DO
  4969.           BEGIN
  4970.               SLOT := STUB^.SLOTS;
  4971.               WHILE SLOT <> NIL DO
  4972.               BEGIN
  4973.                   (*****************  ANALYSE (4.1)  *******************)
  4974.                   (** Use SHADOW_LIST to search a stub with the same  **)
  4975.                   (** name as SLOT^.NAME and update SLOT^.STUB_REF if **)
  4976.                   (** such a stub is found. SLOT^.SRC_IMG serves for  **)
  4977.                   (** a diagnostic if multiple stubs are used in a    **)
  4978.                   (** slot without the MULTIPLE-option                **)
  4979.                   LOCATED := FALSE;
  4980.                   SHADOW_STUB := LIST_HEAD;
  4981.                   WHILE (SHADOW_STUB <> NIL)              AND
  4982.                         (NOT LOCATED)                     AND
  4983.                         (NOT SP_IS_EMPTY_STR(SLOT^.NAME)) DO
  4984.                   BEGIN
  4985.                       STUB_REF := SHADOW_STUB^.STUB_POINTER;
  4986.                       IF SP_EQ (STUB_REF^.NAME, SLOT^.NAME) THEN
  4987.                       BEGIN
  4988.                           LOCATED := TRUE;
  4989.                           SLOT^.STUB_REF := STUB_REF;
  4990.                           IF NOT SLOT^.OPTIONS.MULTIPLE THEN
  4991.                           BEGIN
  4992.                               IF STUB_REF^.NEXT_TWIN <> NIL THEN
  4993.                               BEGIN
  4994.                                   STRING132.LENGTH := 0;
  4995.                                   STRING132.BODY := EMPTY_STRING_FIXED;
  4996.                                   FT_INIT_LINE (DUMMY_LINE);
  4997.                                   DIAG (ERR, 'ANALYSE (4.1)            ', DUMMY_LINE,
  4998.                                               SLOT^.SRC_IMG, STRING132);
  4999.                                   SLOT^.OPTIONS.MULTIPLE := TRUE;
  5000.                               END (*IF*);
  5001.                           END (*IF*);
  5002.                       END
  5003.                       ELSE
  5004.                           SHADOW_STUB := SHADOW_STUB^.NEXT;
  5005.                   END (*WHILE*);
  5006.                   (*************  End of ANALYSE (4.1)  ****************)
  5007.         
  5008.                   SLOT := SLOT^.NEXT_SLOT;
  5009.               END (*WHILE*);
  5010.               STUB := STUB^.NEXT_STUB;
  5011.           END (*WHILE*);
  5012.           (*********************  End of ANALYSE (4)  ******************)
  5013.  
  5014.           (*********************  ANALYSE (5)  *************************)
  5015.           (** Check the resulting structure of CODE_STRUCT for        **)
  5016.           (** circularity. If circularity is detected, break the      **)
  5017.           (** responsible chain and generate a diagnostic.            **)
  5018.         
  5019.           CHECK_CIRC (CODE_STRUCT, LIST_HEAD);
  5020.         
  5021.           (*********************  End of ANALYSE (5)  ******************)
  5022.       END (*IF*)
  5023.       (*********************  End of ANALYSE body  *********************)
  5024.   END (*PROCEDURE ANALYSE*);
  5025.  
  5026.  
  5027.   (*********************************************************************)
  5028.   (* Routine:     GENMOD - MODule GENeration phase                     *)
  5029.   (* Purpose:     Generation of modules out of CODE_STRUCT.            *)
  5030.   (* Interface:   CODE_STRUCT -   Representation of the stub and slot  *)
  5031.   (*                              structure.                           *)
  5032.   (*              RUN_INFO:       User's information for this run.     *)
  5033.   (*********************************************************************)
  5034.   PROCEDURE GENMOD (CODE_STRUCT: CODE_STRUCT_; RUN_INFO: RUN_INFO_);
  5035.  
  5036.   VAR
  5037.       STB_PTR:            STB_PTR_;
  5038.       CONTINUE:           BOOLEAN;
  5039.       LOCATED:            BOOLEAN;
  5040.       OUT_FILE:           TEXT;
  5041.       NR_OPEN_SLOTS,
  5042.       NR_LINES,
  5043.       CORRECTION,
  5044.       INDENT:             INTEGER;
  5045.       AUX_STRING_132 :    STRING_FIXED_;
  5046.       AUX_STRING_9 :      PACKED ARRAY[1..9] OF CHAR;
  5047.       EXTRACTED:          BOOLEAN;
  5048.   CH1, CH2:   CHAR;
  5049.   I:          INTEGER;
  5050.   MODULE_NR:  INTEGER;
  5051.   ERROR_CODE:     ERROR_CODE_;
  5052.   X:              INTEGER;
  5053.   TEMP_FILE_SPEC: STRING132_;
  5054.   REAL_FILE_SPEC: FILE_SPEC_;
  5055.   DUMMY_LINE: LINE_DES_;
  5056.   STRING132:  STRING132_;
  5057.  
  5058.   (*************************  GENMOD routines  *************************)
  5059.  
  5060.   (*********************************************************************)
  5061.   (* Procedure:   BUILDER - BUILDER of module.                         *)
  5062.   (* Purpose:     Build one single module.                             *)
  5063.   (* Interface:   STUB -          Pointer to the starting point of the *)
  5064.   (*                              structure.                           *)
  5065.   (*              OUT_FILE -      File to accept the generated code.   *)
  5066.   (*              NR_OPEN_SLOTS - Number of open slots when ready.     *)
  5067.   (*              NR_LINES -      Number of generated code lines.      *)
  5068.   (*              INDENT -        Current indentation level.           *)
  5069.   (*              CORRECTION -    Correction value for indentation.    *)
  5070.   (*********************************************************************)
  5071.   PROCEDURE BUILDER (STUB:          STB_PTR_;
  5072.                     VAR OUT_FILE:   TEXT;     VAR NR_OPEN_SLOTS: INTEGER;
  5073.                     VAR NR_LINES:   INTEGER;  VAR INDENT:        INTEGER;
  5074.                     VAR CORRECTION: INTEGER);
  5075.  
  5076.   VAR
  5077.       PREV_INDENT:    INTEGER;
  5078.       TWIN_STUB:      STB_PTR_;
  5079.       SLOT:           SLT_PTR_;
  5080.       FIRST,
  5081.       LAST:           INTEGER;
  5082.       INFO_LINE:      LINE_DES_;
  5083.       SEG_LENGTH:     INTEGER;
  5084.       STRING132:      STRING132_;
  5085.       FILE_SPEC:      FILE_SPEC_;
  5086.       K:              INTEGER;
  5087.       DUMMY_FILE:
  5088.                       VARYING
  5089.                       [80]
  5090.                       OF CHAR;
  5091.       DUMMY:
  5092.                       VARYING
  5093.                       [132]
  5094.                       OF CHAR;
  5095.  
  5096.   BEGIN
  5097.       (*********************  BUILDER (body)  **************************)
  5098.       WITH STUB^ DO
  5099.       BEGIN
  5100.           CORRECTION := ST_GET_INDENT (STUB^.SRC_IMG);
  5101.           INDENT := INDENT-CORRECTION;
  5102.           IF STUB^.OPTIONS.LINENUMBER THEN
  5103.           BEGIN
  5104.               (*************************  BUILDER (1)  *********************)
  5105.               (** Use INDENT to write file specification and line number  **)
  5106.               (** of the source file from which STUB^.SRC_IMG is extrac-  **)
  5107.               (** ted to OUT_FILE.                                        **)
  5108.               ST_GET_SEG_RANGE (STUB^.SRC_IMG, FIRST, LAST);
  5109.               ST_GET_FILE_SPEC (STUB^.SRC_IMG, FILE_SPEC);
  5110.               FT_INIT_LINE (INFO_LINE);
  5111.               INFO_LINE.INDENT := ST_GET_INDENT (STUB^.SRC_IMG);            (* !!! *)
  5112.               DUMMY_FILE := '';
  5113.               FOR K := 1 TO FILE_SPEC.LENGTH DO
  5114.                   DUMMY_FILE := DUMMY_FILE + FILE_SPEC.BODY[K];
  5115.               DUMMY := '';
  5116.               WRITE (DUMMY, '(** Line: ', FIRST:1, '   File: ',
  5117.                                                        DUMMY_FILE); (* ISO vreemd  *)
  5118.               SEG_LENGTH := ST_SEG_WIDTH (STUB^.SRC_IMG);
  5119.               FOR K := LENGTH(DUMMY) TO (SEG_LENGTH - 4) DO
  5120.                   DUMMY := DUMMY + ' ';
  5121.               DUMMY := DUMMY + '**)';
  5122.               FOR K := 1 TO LENGTH(DUMMY) DO
  5123.                   INFO_LINE.CHARS[K] := DUMMY[K];                           (* !!! *)
  5124.               INFO_LINE.USED :=  LENGTH(DUMMY);                             (* !!! *)
  5125.               SP_EXTR_STR (STUB^.OPTIONS.INDENT, STRING132);
  5126.               IF (STRING132.BODY[1] = 'O') AND (STRING132.BODY[2] = 'N') THEN
  5127.                   FT_WRLN (INFO_LINE, INDENT,1)
  5128.               ELSE
  5129.                   FT_WRLN (INFO_LINE, 0, 1);
  5130.               (*********************  End of BUILDER (1)  ******************)
  5131.     
  5132.               NR_LINES := NR_LINES+1;
  5133.            END (*IF*);
  5134.     
  5135.           (*************************  BUILDER (2)  *************************)
  5136.           (** Use OPTIONS.COMMENT to decide if STUB^.SRC_IMG needs to be  **)
  5137.           (** written to OUT_FILE. If so, then increase NR_LINES accor-   **)
  5138.           (** dingly and use INDENT to position the segment.              **)
  5139.           SP_EXTR_STR (STUB^.OPTIONS.COMMENT, STRING132);
  5140.           IF (STRING132.BODY[1] = 'O') AND (STRING132.BODY[2] = 'N') THEN
  5141.           BEGIN
  5142.               SP_EXTR_STR (STUB^.OPTIONS.INDENT, STRING132);
  5143.               IF (STRING132.BODY[1] = 'O') AND (STRING132.BODY[2] = 'N') THEN
  5144.                   ST_WRITE_SEG (STUB^.SRC_IMG,INDENT,1)
  5145.               ELSE
  5146.                   ST_WRITE_SEG (STUB^.SRC_IMG,0,1);
  5147.               NR_LINES := NR_LINES + ST_NUMBER_OF_LINES (STUB^.SRC_IMG);
  5148.           END (*IF*);
  5149.           (*********************  End of BUILDER (2)  **********************)
  5150.     
  5151.           SLOT := STUB^.SLOTS;
  5152.           WHILE SLOT <> NIL DO
  5153.           BEGIN
  5154.               (*************************  BUILDER (3)  *********************)
  5155.               (** SLOT inherits the options INDENT and COMMENT from STUB  **)
  5156.               (** when they are not redefined. SLOT also inherits STUB^.- **)
  5157.               (** OPTIONS.LINENUMBER.                                     **)
  5158.               IF SP_IS_EMPTY_STR (SLOT^.OPTIONS.INDENT) THEN
  5159.                   SLOT^.OPTIONS.INDENT := STUB^.OPTIONS.INDENT;
  5160.               IF SP_IS_EMPTY_STR (SLOT^.OPTIONS.COMMENT) THEN
  5161.                   SLOT^.OPTIONS.COMMENT := STUB^.OPTIONS.COMMENT;
  5162.               SLOT^.OPTIONS.LINENUMBER := STUB^.OPTIONS.LINENUMBER;
  5163.               (*********************  End of BUILDER (3)  ******************)
  5164.     
  5165.               IF SLOT^.STUB_REF = NIL THEN
  5166.               BEGIN
  5167.                   (*********************  BUILDER (4)  *********************)
  5168.                   (** SLOT has no reference to a stub. Write segments     **)
  5169.                   (** SLOT^.SRC_IMG and SLOT^.CODE to OUT_FILE using      **)
  5170.                   (** COMMENT and INDENT. Update NR_LINES accodingly.     **)
  5171.                   WITH SLOT^ DO
  5172.                   BEGIN
  5173.                       SP_EXTR_STR (STUB^.OPTIONS.COMMENT, STRING132);
  5174.                       IF (STRING132.BODY[1] = 'O') AND (STRING132.BODY[2] = 'N') THEN
  5175.                       BEGIN
  5176.                           SP_EXTR_STR (SLOT^.OPTIONS.INDENT, STRING132);
  5177.                           IF (STRING132.BODY[1] = 'O') AND (STRING132.BODY[2] = 'N') THEN
  5178.                               ST_WRITE_SEG (SLOT^.SRC_IMG,INDENT,1)
  5179.                           ELSE
  5180.                               ST_WRITE_SEG (SLOT^.SRC_IMG, 0, 1);
  5181.                           NR_LINES := NR_LINES + ST_NUMBER_OF_LINES (SLOT^.SRC_IMG);
  5182.                       END (*IF*);
  5183.                       SP_EXTR_STR (SLOT^.OPTIONS.INDENT, STRING132);
  5184.                       IF (STRING132.BODY[1] = 'O') AND (STRING132.BODY[2] = 'N') THEN
  5185.                           ST_WRITE_SEG (CODE,INDENT,1)
  5186.                       ELSE
  5187.                           ST_WRITE_SEG (CODE, 0, 1);
  5188.                       NR_LINES := NR_LINES + ST_NUMBER_OF_LINES (SLOT^.CODE);
  5189.                   END(*WITH*);
  5190.                   (*****************  End of BUILDER (4)  ******************)
  5191.     
  5192.                   IF (SLOT^.NEXT_SLOT <> NIL)          AND
  5193.                      (NOT SP_IS_EMPTY_STR(SLOT^.NAME)) AND
  5194.                      (NOT SLOT^.OPTIONS.OPTIONAL)          THEN
  5195.                   BEGIN
  5196.                       IF NR_OPEN_SLOTS = 0 THEN
  5197.                       BEGIN
  5198.                           WRITELN ('The following open slots are found:');
  5199.                           WRITELN;
  5200.     
  5201.                           IF REPORT_OK THEN
  5202.                           BEGIN
  5203.                               WRITELN (REPORT_FILE,
  5204.                                       'The following open slots are found:');
  5205.                               WRITELN (REPORT_FILE);
  5206.                           END (*IF*);
  5207.                       END (*IF*);
  5208.     
  5209.                       (* Write slot to terminal and to output file.    *)
  5210.                       ST_WRITE_SEG (SLOT^.SRC_IMG, INDENT, 0);
  5211.                       WRITELN;
  5212.     
  5213.                       IF REPORT_OK THEN
  5214.                       BEGIN
  5215.                           ST_WRITE_SEG (SLOT^.SRC_IMG, INDENT, 3);
  5216.                           WRITELN (REPORT_FILE);
  5217.                       END (*IF*);
  5218.     
  5219.                       NR_OPEN_SLOTS := NR_OPEN_SLOTS+1;
  5220.                   END (*IF*);
  5221.               END
  5222.               ELSE
  5223.               BEGIN
  5224.                   (*********************  BUILDER (5)  *********************)
  5225.                   (** SLOT^.STUB_REF inherits the options INDENT and      **)
  5226.                   (** COMMENT from SLOT if they are not redefined by      **)
  5227.                   (** SLOT^.STUB_REF. SLOT^.STUB_REF also inherits        **)
  5228.                   (** LINENUMBER from SLOT.                               **)
  5229.                   IF SP_IS_EMPTY_STR (SLOT^.STUB_REF^.OPTIONS.INDENT) THEN
  5230.                       SLOT^.STUB_REF^.OPTIONS.INDENT := SLOT^.OPTIONS.INDENT;
  5231.                   IF SP_IS_EMPTY_STR (SLOT^.STUB_REF^.OPTIONS.COMMENT) THEN
  5232.                       SLOT^.STUB_REF^.OPTIONS.COMMENT := SLOT^.OPTIONS.COMMENT;
  5233.                   SLOT^.STUB_REF^.OPTIONS.LINENUMBER := SLOT^.OPTIONS.LINENUMBER;
  5234.                   (*****************  End of BUILDER (5)  ******************)
  5235.     
  5236.                   PREV_INDENT := INDENT;
  5237.                   INDENT := INDENT + ST_GET_INDENT (SLOT^.SRC_IMG);
  5238.                   BUILDER (SLOT^.STUB_REF, OUT_FILE, NR_OPEN_SLOTS,
  5239.                                            NR_LINES, INDENT, CORRECTION);
  5240.                   TWIN_STUB := SLOT^.STUB_REF^.NEXT_TWIN;
  5241.                   WHILE TWIN_STUB <> NIL DO
  5242.                   BEGIN
  5243.                       (*********************  BUILDER (6)  *****************)
  5244.                       (** TWIN_STUB inherits INDENT and COMMENT from      **)
  5245.                       (** SLOT when they are not redefined locally. In    **)
  5246.                       (** addition TWIN_STUB inherits LINENUMBER from     **)
  5247.                       (** SLOT.                                           **)
  5248.                       IF SP_IS_EMPTY_STR (TWIN_STUB^.OPTIONS.INDENT) THEN
  5249.                           TWIN_STUB^.OPTIONS.INDENT := SLOT^.OPTIONS.INDENT;
  5250.                       IF SP_IS_EMPTY_STR (TWIN_STUB^.OPTIONS.COMMENT) THEN
  5251.                           TWIN_STUB^.OPTIONS.COMMENT := SLOT^.OPTIONS.COMMENT;
  5252.                       TWIN_STUB^.OPTIONS.LINENUMBER := SLOT^.OPTIONS.LINENUMBER;
  5253.                       (*****************  End of BUILDER (6)  **************)
  5254.     
  5255.                       INDENT := ST_GET_INDENT (SLOT^.SRC_IMG);
  5256.                       BUILDER (TWIN_STUB, OUT_FILE, NR_OPEN_SLOTS,
  5257.                                           NR_LINES, INDENT, CORRECTION);
  5258.                       TWIN_STUB := TWIN_STUB^.NEXT_TWIN;
  5259.                   END (*WHILE*);
  5260.                   INDENT := PREV_INDENT;
  5261.     
  5262.                   (*********************  BUILDER (7)  *********************)
  5263.                   (** Write the segment SLOT^.CODE to OUT_FILE using the  **)
  5264.                   (** option SLOT^.INDENT.                                **)
  5265.                   SP_EXTR_STR (SLOT^.OPTIONS.INDENT, STRING132);
  5266.                   IF (STRING132.BODY[1] = 'O') AND
  5267.                      (STRING132.BODY[2] = 'F') AND
  5268.                      (STRING132.BODY[3] = 'F')     THEN
  5269.                       ST_WRITE_SEG (SLOT^.CODE, 0, 1)
  5270.                   ELSE
  5271.                       ST_WRITE_SEG (SLOT^.CODE,INDENT,1);
  5272.                   (*****************  End of BUILDER (7)  ******************)
  5273.     
  5274.                   NR_LINES := NR_LINES + ST_NUMBER_OF_LINES (SLOT^.CODE);
  5275.               END (*IF*);
  5276.               SLOT := SLOT^.NEXT_SLOT;
  5277.           END (*WHILE*);
  5278.       END (*WITH*);
  5279.       (*********************  End of BUILDER (body)  *******************)
  5280.   END (*PROCEDURE BUILDER*);
  5281.  
  5282.   (*********************  End of GENMOD routines  **********************)
  5283.  
  5284.   BEGIN
  5285.       (*********************  GENMOD (body)  ***************************)
  5286.       AUX_STRING_9 := 'EXTRACTED';
  5287.       AUX_STRING_132 := EMPTY_STRING_FIXED;
  5288.       FOR I:= 1 TO 9 DO
  5289.           AUX_STRING_132[I] := AUX_STRING_9[I];
  5290.       IF (RUN_INFO.EXTR_MODE <> AUX_STRING_132) THEN
  5291.           EXTRACTED := FALSE
  5292.       ELSE
  5293.           EXTRACTED := TRUE;
  5294.     
  5295.       STB_PTR := CODE_STRUCT.FIRST_STUB;
  5296.       WHILE STB_PTR <> NIL DO
  5297.       BEGIN
  5298.           LOCATED := FALSE;
  5299.           WHILE (STB_PTR <> NIL) AND (NOT LOCATED) DO
  5300.           BEGIN
  5301.               (*************************  GENMOD (1)  **********************)
  5302.               (** If STB_PTR refers to a main stub then use RUN_INFO to   **)
  5303.               (** check if the  module is desired by the user. Raise      **)
  5304.               (** LOCATED if this happens to be the case.                 **)
  5305.               WITH STB_PTR^ DO
  5306.               BEGIN
  5307.                   IF NOT SP_IS_EMPTY_STR (OPTIONS.FILE_NAME) THEN
  5308.                   BEGIN
  5309.                       (*********************  GENMOD (1.1)  ************************)
  5310.                       (** Use RUN_INFO to check if OPTIONS.FILE_NAME indicates a  **)
  5311.                       (** module that is wanted by the user. Raise LOCATED if     **)
  5312.                       (** this is the case. Default the options COMMENT and       **)
  5313.                       (** INDENT it they have not been set explictely.            **)
  5314.                       WITH RUN_INFO DO
  5315.                       BEGIN
  5316.                           CH1 := 'O';
  5317.                           CH2 := 'N';
  5318.                           IF SP_IS_EMPTY_STR (OPTIONS.INDENT) THEN
  5319.                           BEGIN
  5320.                               SP_ADD_CHAR (CH1,OPTIONS.INDENT);
  5321.                               SP_ADD_CHAR (CH2,OPTIONS.INDENT);
  5322.                           END (*IF*);
  5323.                           IF SP_IS_EMPTY_STR (OPTIONS.COMMENT) THEN
  5324.                           BEGIN
  5325.                               SP_ADD_CHAR (CH1,OPTIONS.COMMENT);
  5326.                               SP_ADD_CHAR (CH2,OPTIONS.COMMENT);
  5327.                           END (*IF*);
  5328.                           SP_EXTR_STR (STB_PTR^.OPTIONS.FILE_NAME, TEMP_FILE_SPEC);
  5329.                           LOCATED := FALSE;
  5330.                           FOR X := 1 TO RUN_INFO.NR_MODULES DO
  5331.                           BEGIN
  5332.                               IF TEMP_FILE_SPEC.BODY=
  5333.                                           RUN_INFO.RSLT_MODULES[X].FILE_NAME.BODY THEN
  5334.                               BEGIN
  5335.                                   LOCATED := TRUE;
  5336.                                   MODULE_NR := X;
  5337.                               END (*IF*);
  5338.                           END (*FOR*);
  5339.                     
  5340.                           (* Use the value of EXTRACTED to decide *)
  5341.                           (* whether the module is wanted or not. *)
  5342.                           IF EXTRACTED = FALSE THEN LOCATED := NOT LOCATED;
  5343.                       END (*WITH*);
  5344.                       (*****************  End of GENMOD (1.1)  *********************)
  5345.                   END (*IF*);
  5346.               END (*WITH*);
  5347.               (*********************  End of GENMOD (1)  *******************)
  5348.     
  5349.               IF NOT LOCATED THEN
  5350.                   STB_PTR := STB_PTR^.NEXT_STUB;
  5351.           END (*WHILE*);
  5352.           IF LOCATED THEN
  5353.           BEGIN
  5354.               CONTINUE := TRUE;
  5355.     
  5356.               (*************************  GENMOD (2)  **********************)
  5357.               (** Open OUT_FILE with a name specified by this main stub.  **)
  5358.               (** Set CONTINUE to FALSE if there is a problem. STB_PTR^.- **)
  5359.               (** OPTIONS.FILE_NAME caused the problem and displayed as   **)
  5360.               (** part of an error message.                               **)
  5361.             
  5362.               SP_EXTR_STR (STB_PTR^.OPTIONS.FILE_NAME, TEMP_FILE_SPEC);
  5363.             
  5364.               (* The type of TEMP_FILE_SPEC is not suitable for the File Table     *)
  5365.               (* routine which opens files. It is converted to a REAL_FILE_SPEC.   *)
  5366.             
  5367.               REAL_FILE_SPEC.BODY := EMPTY_STRING_FIXED;
  5368.               REAL_FILE_SPEC.LENGTH := 0;
  5369.             
  5370.               IF EXTRACTED THEN
  5371.               BEGIN
  5372.                   FOR I:= 1 TO RUN_INFO.RSLT_MODULES[MODULE_NR].PATH.LENGTH DO
  5373.                       REAL_FILE_SPEC.BODY[I] :=
  5374.                           RUN_INFO.RSLT_MODULES[MODULE_NR].PATH.BODY[I];
  5375.                   REAL_FILE_SPEC.LENGTH := RUN_INFO.RSLT_MODULES[MODULE_NR].PATH.LENGTH;
  5376.               END
  5377.               ELSE
  5378.               BEGIN
  5379.                   FOR I:= 1 TO RUN_INFO.MODULE_DIRECTORY.LENGTH DO
  5380.                       REAL_FILE_SPEC.BODY[I] := RUN_INFO.MODULE_DIRECTORY.BODY[I];
  5381.                   REAL_FILE_SPEC.LENGTH := RUN_INFO.MODULE_DIRECTORY.LENGTH;
  5382.               END; (*IF*)
  5383.             
  5384.               X := REAL_FILE_SPEC.LENGTH;
  5385.               I := 1;
  5386.               WHILE I <= TEMP_FILE_SPEC.LENGTH DO
  5387.               BEGIN
  5388.                   X:=X+1;
  5389.                   REAL_FILE_SPEC.BODY[X] := TEMP_FILE_SPEC.BODY[I];
  5390.                   I:=I+1;
  5391.               END (*WHILE*);
  5392.               REAL_FILE_SPEC.LENGTH := X;
  5393.             
  5394.               ERROR_CODE := FT_OUTOPEN (REAL_FILE_SPEC);
  5395.               IF ERROR_CODE > 0 THEN
  5396.               BEGIN
  5397.                   CONTINUE := FALSE;
  5398.             
  5399.                   (*********************  GENMOD (2.1)  ****************************)
  5400.                   (** Use STB_PTR^.OPTIONS.FILE_NAME and the returned ERROR_CODE  **)
  5401.                   (** to generate an error message.                               **)
  5402.                   FT_INIT_LINE (DUMMY_LINE);
  5403.                   SP_EXTR_STR (STB_PTR^.OPTIONS.FILE_NAME, STRING132);
  5404.                   DIAG (ERR, 'GENMOD (2.1)             ', DUMMY_LINE,
  5405.                         STB_PTR^.SRC_IMG, STRING132);
  5406.                   (*********************  End of GENMOD (2.1)  *********************)
  5407.               END (*IF*);
  5408.               (*********************  End of GENMOD (2)  *******************)
  5409.     
  5410.               IF CONTINUE THEN
  5411.               BEGIN
  5412.                   NR_OPEN_SLOTS := 0;
  5413.                   NR_LINES := 0;
  5414.     
  5415.                   (*********************  GENMOD (3)  **********************)
  5416.                   (** Generate the module indicated by STB_PTR into       **)
  5417.                   (** OUT_FILE. NR_OPEN_SLOTS and NR_LINES are maintained **)
  5418.                   (** as statistical data.                                **)
  5419.                   WRITE ('Generating file:  ');
  5420.                   FOR X := 1 TO REAL_FILE_SPEC.LENGTH DO
  5421.                       WRITE (REAL_FILE_SPEC.BODY[X]);
  5422.                   WRITELN;
  5423.                 
  5424.                   IF REPORT_OK THEN
  5425.                   BEGIN
  5426.                       WRITE (REPORT_FILE, 'Generating file:  ');
  5427.                       FOR X := 1 TO REAL_FILE_SPEC.LENGTH DO
  5428.                           WRITE (REPORT_FILE, REAL_FILE_SPEC.BODY[X]);
  5429.                       WRITELN (REPORT_FILE);
  5430.                   END (*IF*);
  5431.                 
  5432.                   INDENT :=        ST_GET_INDENT (STB_PTR^.SRC_IMG);
  5433.                   CORRECTION :=    0;
  5434.                   NR_LINES :=      0;
  5435.                   NR_OPEN_SLOTS := 0;
  5436.                   BUILDER (STB_PTR, OUT_FILE, NR_OPEN_SLOTS, NR_LINES,
  5437.                                                              INDENT, CORRECTION);
  5438.                   (*******************  End of GENMOD (3)  *****************)
  5439.     
  5440.                   WRITELN ('Number of open slots in this module: ',
  5441.                             NR_OPEN_SLOTS:1);
  5442.                   WRITELN ('Number of generated lines:  ',NR_LINES:1);
  5443.     
  5444.                   WRITELN ('------------------------------------',
  5445.                            '------------------------------------');
  5446.                   WRITELN;
  5447.     
  5448.                   IF REPORT_OK THEN
  5449.                   BEGIN
  5450.                       WRITELN (REPORT_FILE, 'Number of open slots',
  5451.                                        ' in this module: ', NR_OPEN_SLOTS:1);
  5452.                       WRITELN (REPORT_FILE, 'Number of generated lines:  '
  5453.                                                                 ,NR_LINES:1);
  5454.                       WRITELN (REPORT_FILE,
  5455.                                '------------------------------------',
  5456.                                '------------------------------------');
  5457.                       WRITELN (REPORT_FILE);
  5458.                   END (*IF*);
  5459.     
  5460.                   (*********************  GENMOD (4)  **********************)
  5461.                   (** Close OUT_FILE. Generate an error message in case   **)
  5462.                   (** of trouble.                                         **)
  5463.                   ERROR_CODE := FT_OUTCLOSE;
  5464.                   IF ERROR_CODE <> 0 THEN
  5465.                   BEGIN
  5466.                       (*************************  GENMOD (4.1)  ************************)
  5467.                       (** Use STB_PTR^.OPTIONS.FILE_NAME and STB_PTR^.SRC_IMG to      **)
  5468.                       (** generate a diagnostic message.                              **)
  5469.                       FT_INIT_LINE (DUMMY_LINE);
  5470.                       SP_EXTR_STR (STB_PTR^.OPTIONS.FILE_NAME, STRING132);
  5471.                       DIAG (ERR, 'GENMOD (4.1)             ', DUMMY_LINE,
  5472.                             STB_PTR^.SRC_IMG, STRING132);
  5473.                       (*********************  End of GENMOD (4.1)  *********************)
  5474.                   END(*IF*);
  5475.                   (*****************  End of GENMOD (4)  *******************)
  5476.               END (*IF*);
  5477.               STB_PTR := STB_PTR^.NEXT_STUB;
  5478.           END (*IF*);
  5479.       END (*WHILE*);
  5480.       (*********************  End of GENMOD (body)  ********************)
  5481.  
  5482.   END (*GENMOD*);
  5483.  
  5484.  
  5485.  
  5486.   BEGIN
  5487.       (*******                CLIP_2 (body)                      *******)
  5488.       CONTINUE := TRUE;
  5489.     
  5490.       (*****************************  CLIP_2 (1)  **************************)
  5491.       (** Read the contents of CLIP.INI into RUN_INFO. Set CONTINUE to    **)
  5492.       (** FALSE in case of trouble.                                       **)
  5493.       EXT_FILE_SPEC.BODY := EMPTY_STRING_FIXED;
  5494.       AUX_STRING_8 := DFLT_INIFILE;
  5495.       FOR I := 1 TO 8 DO
  5496.           EXT_FILE_SPEC.BODY[I] := AUX_STRING_8[I];
  5497.       EXT_FILE_SPEC.LENGTH := 8;
  5498.       EXT_FILE_PREP (INI_FILE, EXT_FILE_SPEC, INSP_MODE, DUMMY_FILE_OK,
  5499.                      ERROR_CODE, DUMMY_ERROR_MSG);
  5500.       IF ERROR_CODE > 0 THEN
  5501.       BEGIN
  5502.           WRITELN ('The initializationfile could not be read succesfully.');
  5503.           CONTINUE := FALSE;
  5504.       END
  5505.       ELSE
  5506.       BEGIN                                              (* EWvA: 16/10/93 *)
  5507.           EXT_FILE_CLOSE (INI_FILE, DUMMY_ERROR_CODE);   (* EWvA: 16/10/93 *)
  5508.           READ_INI_FILE (INI_FILE, RUN_INFO, EXT_FILE_SPEC, DUMMY_FILE_OK,
  5509.                          DUMMY_ERROR_MSG, DUMMY_ERROR_CODE);
  5510.       END (* IF *);                                      (* EWvA: 16/10/93 *)
  5511.       (*************************  End of CLIP_2 (1)  ***********************)
  5512.     
  5513.       IF CONTINUE THEN
  5514.       BEGIN
  5515.           (*************************  CLIP_2 (2)  **************************)
  5516.           (** Initialize CODE_STRUCT and the hidden variables of FT, ST,  **)
  5517.           (** SP, SCN_LINE, SCN_OPTS and DIAG_TBL.                        **)
  5518.           FT_INIT;
  5519.           ST_INIT;
  5520.           SP_INIT;
  5521.           SCN_LINE_INIT;
  5522.           SCN_OPTS_INIT;
  5523.           DIAGNOST_INIT;
  5524.           CODE_STRUCT.LAST_STUB  := NIL;
  5525.           CODE_STRUCT.FIRST_STUB := NIL;
  5526.           (*********************  End of CLIP_2 (2)  ***********************)
  5527.     
  5528.           (*************************  CLIP_2 (3)  **************************)
  5529.           (** Prepare a REPORT_FILE file from RUN_INFO.REPORT_FILE_SPEC   **)
  5530.           (** and raise REPORT_OK if this succeeded.                      **)
  5531.                                        (* Modified by EWvA on 16/10/93     *)
  5532.           IF (RUN_INFO.REPORT_FILE_SPEC.BODY <> EMPTY_STRING_FIXED)   AND
  5533.              (RUN_INFO.MESSAGE_DESTINATION[1] IN ['R','r','F','f','B','b'])
  5534.                                        (* End of modification dd. 16/10/93 *)
  5535.           THEN
  5536.           BEGIN
  5537.               EXT_FILE_PREP (REPORT_FILE, RUN_INFO.REPORT_FILE_SPEC, GEN_MODE,
  5538.                              REPORT_OK, ERROR_CODE, ERROR_MSG);
  5539.               IF ERROR_CODE <> 0 THEN
  5540.               BEGIN
  5541.                   WRITELN (OUTPUT, ERROR_MSG);
  5542.                   WRITELN (OUTPUT, 'Continue without report file...');
  5543.                   WRITELN;
  5544.                   REPORT_OK := FALSE;
  5545.               END
  5546.               ELSE
  5547.                   REPORT_OK := TRUE;
  5548.           END
  5549.           ELSE                                          (* EWvA: 16/10/93 *)
  5550.               REPORT_OK := FALSE;                       (* EWvA: 16/10/93 *)
  5551.           (*****************  End of DIAGNOST_EXIT (2)  ********************)
  5552.     
  5553.           START := CLOCK;
  5554.           STOP := START;
  5555.     
  5556.           (*************************  CLIP_2 (4)  **************************)
  5557.           (** Scan the source files as specified in RUN_INFO and build    **)
  5558.           (** the structure of stubs and slots CODE_STRUCT. LPT_FILE_OK   **)
  5559.           (** decides if info for the terminal is copied to REPORT_FILE.  **)
  5560.           WRITELN;
  5561.           WRITELN ('============================ ', CLIP_VERSION,
  5562.                    ' ==========================');
  5563.           WRITELN;
  5564.           WRITELN ('============================ Busy scanning ',
  5565.                    '=============================');
  5566.           IF REPORT_OK THEN
  5567.           BEGIN
  5568.               WRITELN (REPORT_FILE);
  5569.               WRITELN (REPORT_FILE,
  5570.                        '============================ ', CLIP_VERSION,
  5571.                        ' ==========================');
  5572.               WRITELN (REPORT_FILE);
  5573.               WRITELN (REPORT_FILE,
  5574.                        '============================ Busy scanning ',
  5575.                        '=============================');
  5576.           END (*IF*);
  5577.         
  5578.           SCAN_FILES (CODE_STRUCT, RUN_INFO);
  5579.         
  5580.           WRITELN ('============================ End scanning ',
  5581.                    '==============================');
  5582.           WRITELN;
  5583.           IF REPORT_OK THEN
  5584.           BEGIN
  5585.               WRITELN (REPORT_FILE);
  5586.               WRITELN (REPORT_FILE,
  5587.                        '============================ End scanning ',
  5588.                        '==============================');
  5589.           END (*IF*);
  5590.           (*********************  End of  CLIP_2 (4)  **********************)
  5591.     
  5592.           IF CODE_STRUCT.FIRST_STUB <> NIL THEN
  5593.           BEGIN
  5594.               (*************************  CLIP_2 (5)  **********************)
  5595.               (** Analyse CODE_STRUCT. LPT_FILE_OK decides if info to the **)
  5596.               (** terminal is copied to REPORT_FILE also.                 **)
  5597.               WRITELN ('============================ Busy analysing ',
  5598.                        '============================');
  5599.               IF REPORT_OK THEN
  5600.               BEGIN
  5601.                   WRITELN (REPORT_FILE);
  5602.                   WRITELN (REPORT_FILE,
  5603.                            '============================ Busy analysing ',
  5604.                            '============================');
  5605.               END (*IF*);
  5606.             
  5607.               ANALYSE (CODE_STRUCT);
  5608.             
  5609.               WRITELN ('============================ End analysing ',
  5610.                        '=============================');
  5611.               WRITELN;
  5612.               IF REPORT_OK THEN
  5613.               BEGIN
  5614.                   WRITELN (REPORT_FILE);
  5615.                   WRITELN (REPORT_FILE,
  5616.                            '============================ End analysing ',
  5617.                            '=============================');
  5618.               END (*IF*);
  5619.               (*********************  End of CLIP_2 (5)  *******************)
  5620.     
  5621.               (*************************  CLIP_2 (6)  **********************)
  5622.               (** Generate the modules as specified in RUN_INFO out of    **)
  5623.               (** CODE_STRUCT. LPT_FILE_OK decides if info for terminal   **)
  5624.               (** is also copied to REPORT_FILE.                          **)
  5625.               WRITELN ('============================ Busy generating ',
  5626.                        '===========================');
  5627.               IF REPORT_OK THEN
  5628.               BEGIN
  5629.                   WRITELN (REPORT_FILE);
  5630.                   WRITELN (REPORT_FILE,
  5631.                            '============================ Busy generating ',
  5632.                            '===========================');
  5633.               END (*IF*);
  5634.             
  5635.               GENMOD (CODE_STRUCT, RUN_INFO);
  5636.             
  5637.               WRITELN ('============================ End generating ',
  5638.                        '============================');
  5639.               WRITELN;
  5640.               IF REPORT_OK THEN
  5641.               BEGIN
  5642.                   WRITELN (REPORT_FILE);
  5643.                   WRITELN (REPORT_FILE,
  5644.                            '============================ End generating ',
  5645.                            '============================');
  5646.               END (*IF*);
  5647.               (*********************  End of CLIP_2 (6)  *******************)
  5648.     
  5649.               STOP := CLOCK;
  5650.           END (*IF*);
  5651.     
  5652.       (*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  5653.               +++++++++++   EWvA, jan6, 1993: Report file   ++++++++++++
  5654.           FT_INIT_LINE (DUMMY_LINE);
  5655.           ST_INIT_SEG (DUMMY_SEG);
  5656.           STRING132.LENGTH := 0;
  5657.           STRING132.BODY := EMPTY_STRING_FIXED;
  5658.           DIAG (WARN, 'CLIP_2                   ', DUMMY_LINE, DUMMY_SEG,
  5659.                 STRING132);
  5660.       ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
  5661.     
  5662.       (* Generate error messages to terminal and possibly report file      *)
  5663.       DIAGNOST_EXIT;
  5664.     
  5665.           (* Delete the segment-table.                                 *)
  5666.           ST_FINIT;
  5667.     
  5668.           (* Display a goodbye message.                                *)
  5669.           WRITELN ('Used (CPU) time :', (STOP-START)/1000:4:2, ' Sec.');
  5670.           WRITELN ('See you next time !');
  5671.     
  5672.           IF REPORT_OK THEN
  5673.           BEGIN
  5674.               WRITELN (REPORT_FILE, 'Used (CPU) time :',
  5675.                                              (STOP-START)/1000:4:2, ' Sec.');
  5676.               WRITELN (REPORT_FILE, 'See you next time !');
  5677.               EXT_FILE_CLOSE (REPORT_FILE, DUMMY_ERROR);
  5678.           END (*FI*);
  5679.       END (*IF*);
  5680.       (*********************  End of CLIP_2 (body)  ********************)
  5681.   END (*CLIP_2*).
  5682.   (*******************  End of module clip_unix.pas  *******************)
  5683.